2016-08-08 6 views
3

나는 이것과 비슷한 수천 개의 행을 가진 테이블을 가지고있다.특정 문자열을 반환하는 방법

note 
---- 
LB MN IM 12 18 20 CIN # EW80851R This is tJ 
ified KGM nteal icne cinac12345T Cannot locate 
NCR Last verified 06 05 14 cin number ty56478P for the front 
OD 00612 Last Verified cin#ad89521Y Me side C 05 05 14 
SPC 0 VERIFIED PD IMB cin PU12301R Last Verified 
PC PO CON FC D Verified 02/29/2016 No Copy CIN#FG62301F 

각 행의 뒤에는 단어 cin과 몇 개의 문자가옵니다. 예를 들어

: CIN # EW80851R, cinac12345T, cin number ty56478P, cin#ad89521Y, cin PU12301R, CIN#FG62301F

가 어떻게 만 반환하는 쿼리를 작성합니다

note 
---- 
cinEW80851R 
cinac12345T 
cinty56478P 
cinad89521Y 
cinPU12301R 
CINFG62301F 

답변

1

을 XML의 도움으로, 문자열 파서와 크로스 적용, 당신은 당신의 전체 데이터를 처리 할 수 ​​있습니다 세트.

당신은 문자 장난으로 만 # 있다고 가정하면 나는 두 번째 레코드

Declare @YourTable table (ID int,Note varchar(max)) 
Insert into @YourTable values 
(1,'LB MN IM 12 18 20 CIN # EW80851R This is tJ ified KGM nteal icne cinac12345T Cannot locate NCR Last verified 06 05 14 cin number ty56478P for the front OD 00612 Last Verified cin#ad89521Y Me side C 05 05 14 SPC 0 VERIFIED PD IMB cin PU12301R Last Verified PC PO CON FC D Verified 02/29/2016 No Copy CIN#FG62301F'), 
(2,'L This is tJ KGM teal icne Last verified 06 05 14 for the front OD 00612 Last Verified cin#ZZ89256Y Me side C 05 05 14 SPC 0 VERIFIED PD IMB cin ZZPU12301R Last Verified PC PO CON FC D Verified 02/29/2016 No Copy CIN#ZZ62301F') 

-- Create a Mapping/Normaization Table 
Declare @Map table (MapSeq int,MapFrom varchar(25),MapTo varchar(25)) 
Insert into @Map values (1,char(13),' '),(2,char(10),' '),(3,' cin number ',' cin'),(4,' cin # ',' cin'),(5,' cin#',' cin'),(6,' cin ',' cin') 

-- Convert your Base Data to XML 
Declare @XML XML,@String varchar(max) 
Set @XML = (Select KeyID=ID,String=+' '+Note+' ' from @YourTable For XML RAW) 

-- Convert XML to Varchar(max) and Apply Global Search & Replace 
Select @String = cast(@XML as varchar(max)) 
Select @String = Replace(@String,MapFrom,MapTo) From @Map Order by MapSeq 

-- Convert Back to XML 
Select @XML = cast(@String as XML) 

-- Generate Final Results 
Select A.ID 
     ,CIN = B.Key_Value 
From (
     Select ID  = t.col.value('@KeyID', 'int') 
       ,NewString = t.col.value('@String', 'varchar(max)') 
     From @XML.nodes('/row') AS t (col) 
    ) A 
Cross Apply (Select * from [dbo].[udf-Str-Parse](A.NewString,' ') where Key_Value like 'cin%') B 

반환

ID CIN 
1 cinEW80851R 
1 cinac12345T 
1 cinty56478P 
1 cinad89521Y 
1 cinPU12301R 
1 cinFG62301F 
2 cinZZ89256Y  << Dummy Record 
2 cinZZPU12301R << Dummy Record 
2 cinZZ62301F  << Dummy Record 

을 추가한다는 UDF

CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimeter varchar(10)) 
--Usage: Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',') 
--  Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ') 
--  Select * from [dbo].[udf-Str-Parse]('id26,id46|id658,id967','|') 
--  Select * from [dbo].[udf-Str-Parse]('hello world. It. is. . raining.today','.') 

Returns @ReturnTable Table (Key_PS int IDENTITY(1,1), Key_Value varchar(max)) 
As 
Begin 
    Declare @XML xml;Set @XML = Cast('<x>' + Replace(@String,@Delimeter,'</x><x>')+'</x>' as XML) 
    Insert Into @ReturnTable Select Key_Value = ltrim(rtrim(String.value('.', 'varchar(max)'))) FROM @XML.nodes('x') as T(String) 
    Return 
End 
+0

심각한 해결책 +1 정규화 표에 모든 숫자가 아닌 문자 기호를 추가하는 것이 좋습니다. – gofr1

1

주의 것이고, 길이 당신이 필요로하는 부분은 8이고이 값의 3에서 7까지의 부분은 int입니다. 르 - 당신은 다음과 같이 XML (XQuery를) 사용하려고 할 수 있습니다 : 귀하가 제공 한 테이블 부분에서

DECLARE @xml xml 

SELECT @xml = (
    SELECT CAST('<d>'+REPLACE(REPLACE(SUBSTRING(Note,CHARINDEX('cin',Note)+3,LEN(Note)),' ','#'),'#','</d><d>')+'</d>' as xml) 
    FROM YourTable 
    FOR XML PATH('') 
) 

SELECT t.v.value('.','nvarchar(8)')   
FROM @xml.nodes('/d') as t(v) 
WHERE LEN(t.v.value('.','nvarchar(8)')) = 8 --check if length = 8 
    AND ISNULL(t.v.value('substring(string(.), 3, 5) cast as xs:int ?','int'),0) != 0 --check if part of value is int 

가 출력 될 것입니다 : (@ JohnCappelleti의 솔루션에서 영감)

EW80851R 
ac12345T 
ty56478P 
ad89521Y 
PU12301R 
FG62301F 

편집

더 복잡한 솔루션 :

--Declare variables 
DECLARE @xml xml, @string nvarchar(max) = '' 
--Rows becomes one big string 
SELECT @string = @string + SUBSTRING(Note,CHARINDEX('cin',Note)+3,LEN(Note)) +' ' 
FROM YourTable y 
--CTE with all not numeric and not alphabetical charecters for normalization 
;WITH Symbols AS (
    SELECT 0 as d, 
      CHAR(0) as s, 
      1 as isUsed 
    UNION ALL 
    SELECT d+1, 
      CHAR(d+1), 
      CASE WHEN d+1 between 48 and 57 
        OR d+1 between 65 and 90 
        OR d+1 between 97 and 122 THEN 0 ELSE 1 END 
    FROM Symbols 
    WHERE d < 255 
) 
--replace all not numeric and not alphabetic 
SELECT @string = REPLACE(@string,s.s,'#') 
FROM Symbols s 
WHERE isUsed = 1 
OPTION(MAXRECURSION 0) 
--convert to xml 
SELECT @xml= CAST('<d>'+REPLACE(@string,'#','</d><d>')+'</d>' as xml) 
--convert XML to table 
SELECT t.v.value('.','nvarchar(8)')   
FROM @xml.nodes('/d') as t(v) 
WHERE LEN(t.v.value('.','nvarchar(8)')) = 8 --check if length = 8 
    AND ISNULL(t.v.value('substring(string(.), 3, 5) cast as xs:int ?','int'),0) != 0 
    --check if part of value is int 
+0

Plus1 좋아, 멋지다 - 내 대답을 삭제했다. –

관련 문제