2010-11-16 127 views
1

從下表中,如何將Values列轉換爲多列,並填充單獨的值,這些值當前由逗號分隔?在轉換前:T-SQL - 將逗號分隔的列轉換爲多列

Name Values 
---- ------ 
John val,val2,val3 
Peter val5,val7,val9,val14 
Lesli val8,val34,val36,val65,val71,val 
Amy val3,val5,val99 

轉換的結果應該是這樣的:

Name Col1 Col2 Col3 Col4 Col5 Col6 
---- ---- ---- ---- ---- ---- ---- 
John val val2 val3 
Peter val5 val7 val9 val14 
Lesli val8 val34 val36 val65 val71 val 
Amy val3 val5 val99 
+0

請轉換格式化您的表了一點,所以我們可以使你的要求更有意義。 – Stu 2010-11-17 00:49:18

+0

剛剛上傳的圖片無法格式化表格。 – user219628 2010-11-17 03:08:59

+0

感謝您的反饋。 – user219628 2010-11-17 03:11:09

回答

3

首先,你使用的是什麼數據庫產品和版本?如果您在使用SQL Server 2005及更高版本,你可以寫一個分離的用戶定義函數,像這樣:

CREATE FUNCTION [dbo].[Split] 
( 
    @DelimitedList nvarchar(max) 
    , @Delimiter varchar(2) = ',' 
) 
RETURNS TABLE 
AS 
RETURN 
    (
    With CorrectedList As 
     (
     Select Case When Left(@DelimitedList, DataLength(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End 
      + @DelimitedList 
      + Case When Right(@DelimitedList, DataLength(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End 
      As List 
      , DataLength(@Delimiter) As DelimiterLen 
     ) 
     , Numbers As 
     (
     Select TOP (Coalesce(Len(@DelimitedList),1)) Row_Number() Over (Order By c1.object_id) As Value 
     From sys.objects As c1 
      Cross Join sys.columns As c2 
     ) 
    Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position 
     , Substring (
        CL.List 
        , CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen  
        , CharIndex(@Delimiter, CL.list, N.Value + 1)       
         - (CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen) 
        ) As Value 
    From CorrectedList As CL 
     Cross Join Numbers As N 
    Where N.Value < Len(CL.List) 
     And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter 
    ) 

然後可以打出值你想用一個類似於:

Select Name, Values 
From Table1 As T1 
Where Exists (
       Select 1 
       From Table2 As T2 
        Cross Apply dbo.Split (T1.Values, ',') As T1Values 
        Cross Apply dbo.Split (T2.Values, ',') As T2Values 
       Where T2.Values.Value = T1Values.Value 
        And T1.Name = T2.Name 
       ) 
+0

謝謝,它的工作太 – user219628 2010-11-19 17:41:12

3

這是一個解決方案,它使用遞歸cte來生成「table of numbers」(禮貌Itzik Ben-Gan),它是useful,適用於所有問題,包括字符串拆分和PIVOT。 SQL Server 2005起。包括全表創建,插入和選擇腳本。

CREATE TABLE dbo.Table1 
(
    Name  VARCHAR(30), 
    [Values] VARCHAR(128) 
) 
GO 

INSERT INTO dbo.Table1 VALUES ('John', 'val,val2,val3') 
INSERT INTO dbo.Table1 VALUES ('Peter', 'val5,val7,val9,val14') 
INSERT INTO dbo.Table1 VALUES ('Lesli', 'val8,val34,val36,val65,val71,val') 
INSERT INTO dbo.Table1 VALUES ('Amy', 'val3,val5,val99') 
GO 

SELECT * FROM dbo.Table1; 
GO 

WITH 
L0 AS(SELECT 1 AS c UNION ALL SELECT 1), 
L1 AS(SELECT 1 AS c FROM L0 AS A, L0 AS B), 
L2 AS(SELECT 1 AS c FROM L1 AS A, L1 AS B), 
L3 AS(SELECT 1 AS c FROM L2 AS A, L2 AS B), 
Numbers AS(SELECT ROW_NUMBER() OVER(ORDER BY c) AS n FROM L3) 
SELECT Name, [1] AS Column1, [2] AS Column2, [3] AS Column3, [4] AS Column4, [5] AS Column5, [6] AS Column6, [7] AS Column7 
FROM 
(SELECT Name, 
     ROW_NUMBER() OVER (PARTITION BY Name ORDER BY nums.n) AS PositionInList, 
     LTRIM(RTRIM(SUBSTRING(valueTable.[Values], nums.n, charindex(N',', valueTable.[Values] + N',', nums.n) - nums.n))) AS [Value] 
FROM Numbers AS nums INNER JOIN dbo.Table1 AS valueTable ON nums.n <= CONVERT(int, LEN(valueTable.[Values])) AND SUBSTRING(N',' + valueTable.[Values], n, 1) = N',') AS SourceTable 
PIVOT 
(
MAX([VALUE]) FOR PositionInList IN ([1], [2], [3], [4], [5], [6], [7]) 
) AS Table2 
GO 

--DROP TABLE dbo.Table1 

此輸出

Name Values 
John val,val2,val3 
Peter val5,val7,val9,val14 
Lesli val8,val34,val36,val65,val71,val 
Amy val3,val5,val99 

Name Column1 Column2 Column3 Column4 Column5 Column6 Column7 
Amy val3 val5 val99 NULL NULL NULL NULL 
John val  val2 val3 NULL NULL NULL NULL 
Lesli val8 val34 val36 val65 val71 val  NULL 
Peter val5 val7 val9 val14 NULL NULL NULL 
+0

我應該補充說,這個的缺點是,你不能動態調整列的數量取決於逗號分隔的值的最大數量串。爲此,您需要考慮動態SQL並構建列數等於任何一個分隔字符串中的最大值。 – 2010-11-17 18:13:46

相關問題