2016-06-22 4 views
0

쉼표로 구분 된 ID 목록을 쉼표로 구분 된 접두사 목록으로 변환하려고합니다. 에 의해 코멘트에서 언급 한 바와 같이쉼표로 구분 된 ID 목록을 쉼표로 구분 된 접두사로 변환하십시오. SQL Server

BKR394859607,MTP293840284,SPN489620586 

내 목표는 IDS

Declare @ActivityID as varchar(MAX) = 'BKR394859607,MTP293840284,SPN489620586' 
Declare @ActivityPrefixes as varchar(MAX) 
Set @ActivityPrefixes = (function to Convert to comma delimited prefix list) 
+0

당신이 구분 된 목록 대신 임시 테이블, 테이블 변수 나 테이블 반환 매개 변수를 사용할 수 –

+2

항상 처음 세 글자 수 있습니까? 이것을 문자열로 처리하려면 먼저 테이블로 분할 한 다음 처음 세 문자를 제외하고 모두 제거한 다음 다시 모두 구분 된 목록으로 다시 밀어 넣어야합니다. –

+0

예 접두사는 항상 처음 세 글자입니다. 또한 SQL Server 2014를 사용하고 있습니다. – GnisPL

답변

2

의 무한한을 가질 수

BKR,MTP,SPN 

이 문자열로 SQL 서버 내 IDString에서이 3 개 ID를 변환하는 것입니다 Sean Lange, 세 단계 수행해야 함

  1. 문자열을 개별 행으로 분할하십시오.
  2. 필요한 문자를 제거하십시오.
  3. 행을 다시 CSV로 연결하십시오. 이

    DECLARE @ActivityID AS VARCHAR(max) = 
         'BKR394859607,MTP293840284,SPN489620586,GHY489620586' 
    
    SELECT Stuff(split_val, 1, 1, '') as Result 
    FROM (SELECT ',' 
           + LEFT(split.a.value('.', 'VARCHAR(100)'), 3) 
         FROM (SELECT Cast ('<M>' + Replace(@ActivityID, ',', '</M><M>') 
              + '</M>' AS XML) AS Data) AS A 
           CROSS apply data.nodes ('/M') AS Split(a) 
         FOR xml path(''))a(split_val) 
    

    결과 같은

뭔가 :BKR,MTP,SPN,GHY

+0

트릭을 수행했습니다. 감사합니다. – GnisPL

1

이 시도 :

DECLARE @ActivityID AS VARCHAR(MAX) = 'BKR394859607,MTP293840284,SPN489620586'; 

DECLARE @ActivityPrefixes AS VARCHAR(MAX); 

SET @ActivityPrefixes = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
    REPLACE(REPLACE(REPLACE(REPLACE(
     @ActivityID,'0', ''), '1',''), '2', ''),'3', ''), '4',''), '5', ''), 
        '6', ''),'7', ''), '8', ''), '9', ''); 
SELECT @ActivityPrefixes 

당신이 다음이 시도 각 섹션의 처음 3 문자를 얻고 싶다면 :

DECLARE @ActivityID AS VARCHAR(MAX) = 'BKR39A859607,M3TP293840284,SP1N4896GG586,BKR394859607,MTP293840284,SPN489620586'; 

DECLARE @ActivityPrefixes AS VARCHAR(MAX); 
SET @ActivityPrefixes = ''; 

WHILE 1 = 1 
BEGIN 

    DECLARE @i INT; 

    IF CHARINDEX(',', @ActivityID) = 0 
     SET @i = 3; 
    ELSE 
     SET @i = CHARINDEX(',', @ActivityID) - 1; 

    IF @ActivityPrefixes = '' 
     SET @ActivityPrefixes = SUBSTRING(SUBSTRING(@ActivityID, 1, @i), 1,3); 
    ELSE 
     SET @ActivityPrefixes = @ActivityPrefixes + ',' 
      + SUBSTRING(SUBSTRING(@ActivityID, 1, @i), 1, 3); 

    IF CHARINDEX(',', @ActivityID) = 0 
     BREAK; 

    SET @ActivityID = SUBSTRING(@ActivityID,CHARINDEX(',', @ActivityID) + 1,LEN(@ActivityID)); 
END; 

SELECT @ActivityPrefixes; 
+1

처음 3 자에 숫자가 포함되어 있거나 다른 문자가 숫자가 아닌 경우에는 작동하지 않습니다. –

+0

@SeanLange이 접근법이 작동하지 않는 데이터 예제를 제공하십시오. –

+0

내가 제공 한 테스트 데이터와 잘 작동하며 가장 간단합니다. 그러나 실제 데이터에는 문자가 때때로 포함되어 있습니다. – GnisPL

1

맨 먼저 다음 기사를 읽고, 문자열 분리 (및 수행하지 않을 이유)에 대해 논의하고 피할 수없는 경우 수행 할 방법의 성능을 비교하십시오.

  1. 피 구분 된 목록을 문자열 곳으로 :

    이 세 기사의 결말은 (경우에 링크는 지금까지 죽은 될)입니다 가능하면 목록을 저장해야하는 경우 표가 훨씬 더 좋습니다.

  2. 수행해야 할 경우 CLR이 가장 확장 가능하고 정확한 방법입니다.
  3. 분할 할 특수 XML 문자가 없다는 것을 확신 할 수 있다면 구분 된 문자열을 XML로 변환 한 다음 XQuery를 사용하여 개별 항목을 올바르게 가져올 수 있습니다.
  4. 그렇지 않으면 교차 결합을 사용하여 집계 테이블을 만드는 것이 나머지 중 가장 좋습니다.

모두가 CLR을 사용하고, 특별한 XML 문자를 보장 할, 그래서에 대한 분할 방법은 수 있기 때문에 가장 다재다능한 방법은 마지막 :

CREATE FUNCTION [dbo].[Split] 
(
    @List  NVARCHAR(MAX), 
    @Delimiter NVARCHAR(255) 
) 
RETURNS TABLE 
WITH SCHEMABINDING AS 
RETURN 
( WITH N1 AS (SELECT N FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1), (1)) n (N)), 
    N2(N) AS (SELECT 1 FROM N1 a CROSS JOIN N1 b), 
    N3(N) AS (SELECT 1 FROM N2 a CROSS JOIN N2 b), 
    N4(N) AS (SELECT 1 FROM N3 a CROSS JOIN N3 b), 
    cteTally(N) AS 
    ( SELECT 0 UNION ALL 
     SELECT TOP (DATALENGTH(ISNULL(@List,1))) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) 
     FROM n4 
    ), 
    cteStart(N1) AS 
    ( SELECT t.N+1 
     FROM cteTally t 
     WHERE (SUBSTRING(@List,t.N,1) = @Delimiter OR t.N = 0) 
    ) 
    SELECT Item = SUBSTRING(@List, s.N1, ISNULL(NULLIF(CHARINDEX(@Delimiter,@List,s.N1),0)-s.N1,8000)), 
      Position = s.N1, 
      ItemNumber = ROW_NUMBER() OVER(ORDER BY s.N1) 
    FROM cteStart s 
); 

지금 당신은 당신의 분할 기능을 가지고

DECLARE @ActivityID AS VARCHAR(MAX) = 'BKR394859607,MTP293840284,SPN489620586'; 

SELECT Item, 
     NewID = LEFT(Item, 3) 
FROM dbo.Split(@ActivityID, ','); 

당신에게 제공합니다 :

Item   NewID 
----------------------------- 
BKR394859607 BKR 
MTP293840284 MTP 
SPN489620586 SPN 
을, 당신은 당신의 첫 번째 문자열을 분할 할 수 있습니다

그럼 당신은 FOR XML PATH()를 사용하여이를 다시 연결할 수 있습니다 자세한 내용은

DECLARE @ActivityID AS VARCHAR(MAX) = 'BKR394859607,MTP293840284,SPN489620586'; 

SELECT STUFF((SELECT ',' + LEFT(Item, 3) 
       FROM dbo.Split(@ActivityID, ',') 
       FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 1, ''); 

을이 작품 this answer를 볼 방법에. , 구분 된 문자열을 구축하기보다는 그런

CREATE TYPE dbo.StringList AS TABLE (Value VARCHAR(MAX)); 

테이블 구축 : 다음

DECLARE @Activity dbo.StringList; 
INSERT @Activity (Value) 
VALUES ('BKR394859607'), ('MTP293840284'), ('SPN489620586'); 

최적의 솔루션은 아마도 문자열 목록을 저장하는 사용자 정의 테이블 형식을 가지고하는 것입니다 당신은 고통스럽지 않은 분할을 피하고, 각 개별 기록을 쉽게 조작 할 수 있습니다. 당신이 정말로 새로운 구분 된 문자열을 얻을 필요 않은 경우

는, 당신은 위와 동일한 논리를 사용할 수 있습니다

DECLARE @Activity dbo.StringList; 
INSERT @Activity (Value) 
VALUES ('BKR394859607'), ('MTP293840284'), ('SPN489620586'); 

SELECT STUFF((SELECT ',' + LEFT(Value, 3) 
       FROM @Activity 
       FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 1, ''); 
1

T-SQLregeular 표현 기능을 구현하기 위해 다음과 같은 answer를 사용합니다. 그런 다음 사용하여 다음을 수행 할 수 있습니다

enter image description here

관련 문제