2017-08-01 74 views
1

我需要將單列中的數據拆分爲多列。
我有這樣如何在滿足特殊字符時拆分列

ID  NAME    COMMENT 
1  TEST  Reg: 0001 Inv: B0001 Cus: A0001 Br: F0001 
2  TEST1  Reg: 0002 Inv: B0002 Cus: A0002 Br: F0002 
3  TEST2  Reg: 0003 Inv: B0003 Cus: A0003 Br: F0003 
4  TEST3  Reg: 0004 Inv: B0004 Cus: A0004 Br: F0004 
5  TEST4  Reg: 0005 Inv: B0005 Cus: A0005 Br: F0005 
5  TEST4  Reg: 00010 Inv: B00010 Cus: A00010 Br: F00010 

的數據,我需要拆表評論中的數據,所以它變成了這個樣子:

REG  INV  BR 
0001  B0001 F0001 
0002  B0002 F0002 
0003  B0003 F0003 
0004  B0004 F0004 
0005  B0005 F0005 
00010  B00010 F00010  

任何建議,如何做到這一點?

我的代碼。

;WITH Split_Names (Comment) 
    AS 
    -- Define the CTE query. 
    (
     SELECT 
     CONVERT(XML,'<COMMENTS><Comment>' 
     + REPLACE(
    REPLACe(
    REPLACE(
    REPLACE(
    REPLACE(
    REPLACE(Comment,'Reg:',''),'Inv:',','),'Cus:',','),'Br:',','),' ' ,'') 
     ,',', '</Comment><Comment>') + '</Comment></COMMENTS>') AS xmlComments 
     FROM GenTransaction 
    ) 
    -- Define the outer query referencing the CTE name. 
    SELECT  
    Comment.value('/COMMENTS[1]/Comment[1]','varchar(100)') AS Reg,  
    Comment.value('/COMMENTS[1]/Comment[2]','varchar(100)') AS Inv, 
    Comment.value('/COMMENTS[1]/Comment[3]','varchar(100)') AS Cus, 
    Comment.value('/COMMENTS[1]/Comment[4]','varchar(100)') AS Br 

    FROM Split_Names 
+1

什麼版本的SQL Server您使用的是? – SQLAndOtherStuffGuy

+1

我的建議是將您的數據導入到您實際需要的列中。在SQL Server內部不是做這種清理的最佳選擇。 –

+0

感謝,版本10.50.1617.0 – tang

回答

2

以下解決方案應該工作

[1]沒有哪個順序用於Comment柱(Reg, Inv, Cus BrCus, Br, Reg, Inv或別的東西)和項目內容還

[2] Comment一些項目列可能會丟失(例如TEST4/Cus丟失)

[3]如果Comment包含XML保留字符,則代替REPLACE(t1.Comment,應該用REPLACE((SELECT t1.Comment AS '*' FOR XML PATH('')),

DECLARE @Table1 TABLE (
    ID  INT NOT NULL, 
    Name NVARCHAR(50), 
    Comment NVARCHAR(500) 
); 
INSERT @Table1 (ID, Name, Comment) 
VALUES 
(1, 'TEST ', 'Reg: 0001 Inv: B0001 Cus: A0001 Br: F0001'), 
(2, 'TEST1', 'Reg: 0002 Inv: B0002 Cus: A0002 Br: F0002'), 
(3, 'TEST2', 'Reg: 0003 Inv: B0003 Cus: A0003 Br: F0003'), 
(4, 'TEST3', 'Reg: Coco&Jambo Inv: B0004 Cus: A0004 Br: F0004'), -- & = reserved XML char 
(5, 'TEST4', 'Reg: 0005 Inv: B0005 Br: F0005'), -- Cus is missing 
(5, 'TEST4', 'Cus: 3333 Br: 4444 Reg: 1111 Inv: 22222'); -- Different order 

;WITH BaseQuery AS 
(
    SELECT t1.ID, t1.Name, 
       CONVERT(XML, '<root><item>' 
       + REPLACE(
        REPLACE(
         REPLACE(
          REPLACE((SELECT t1.Comment AS '*' FOR XML PATH('')), 
          'Reg:', 
          '</item><item type="Reg">'), 
         'Inv:', 
         '</item><item type="Inv">'), 
        'Cus:', 
        '</item><item type="Cus">'), 
       'Br:', 
       '</item><item type="Br">') + '</item></root>') CommentAsXml 
    FROM @Table1 t1 
) 
SELECT bq.ID, bq.Name, 
     Reg = LTRIM(RTRIM(bq.CommentAsXml.value('(root/item[@type="Reg"])[1]', 'VARCHAR(11)'))), 
     Inv = LTRIM(RTRIM(bq.CommentAsXml.value('(root/item[@type="Inv"])[1]', 'VARCHAR(11)'))), 
     Cus = LTRIM(RTRIM(bq.CommentAsXml.value('(root/item[@type="Cus"])[1]', 'VARCHAR(11)'))), 
     Br = LTRIM(RTRIM(bq.CommentAsXml.value('(root/item[@type="Br"])[1]', 'VARCHAR(11)'))) 
FROM BaseQuery bq 

結果:

enter image description here

Demo here

+0

Msg 9411,Level 16,State 1,Line 1 XML解析:行1,字符45,預期分號 Msg 9421,級別16,狀態1,行1 XML解析:行1,字符44 ,非法名字字符 – tang

+0

我得到這個錯誤 – tang

+0

第1行來自「------; WITH BaseQuery AS ----」 – tang

1

試試這個。基本上我正在做的是用逗號代替Reg:Inv:等,去除空格並使用XML來派生列值。

enter image description here

所以我reffering到@Bogdan下面的註釋字段處理XML特殊字符Sahlean解決方案。嘗試這個;

 ;WITH Split_Names (COMMENT) 
     AS 
     -- Define the CTE query. 
     (
      SELECT 
      CONVERT(XML,'<COMMENTS><COMMENT>' 
    + 
    REPLACE(
    REPLACe(
    REPLACE(
    REPLACE(
    REPLACE(
    REPLACE(
    (SELECT Comment AS '*' FOR XML PATH('')) 
    ,'Reg:',''),'Inv:',','),'Cus:',','),'Br:',','),' ' ,'') 
    ,',', '</COMMENT><COMMENT>') + '</COMMENT></COMMENTS>') AS xmlname 
      FROM 


GenTransaction 
     ) 
     -- Define the outer query referencing the CTE name. 
     SELECT  
     COMMENT.value('/COMMENTS[1]/COMMENT[1]','varchar(100)') AS Reg,  
     COMMENT.value('/COMMENTS[1]/COMMENT[2]','varchar(100)') AS Inv, 
     COMMENT.value('/COMMENTS[1]/COMMENT[3]','varchar(100)') AS Cus, 
     COMMENT.value('/COMMENTS[1]/COMMENT[4]','varchar(100)') AS Br 

     FROM Split_Names 
+0

對不起,我不熟悉CTE什麼應該我把xmlname? – tang

+0

將YOURTABLENAME替換爲您正在使用的表的名稱。 – SQLAndOtherStuffGuy

+0

「---- Msg 9421,Level 16,State 1,Line 1 XML解析:行1,字符44,非法名稱字符-----」我得到這個錯誤 – tang