2

以下のようなデータがあります

Declare @t table (Id int identity,CommaSeperatedValue varchar(100))
Insert Into @t 
Select 'Somalia,Vietnam' Union All 
Select 'apple,banana,guava,India,Australia'

CommaSeperated 値に制限はありません。提供されたサンプルの望ましい出力は次のようになります。

Id  Col1    Col2    Col3    Col4    Col5
1   Somalia Vietnam Null    Null    Null
2   apple   banana  guava   India   Australia

つまり、列は動的に生成されます。別の例を見てみましょう

Declare @t table (Id int identity,CommaSeperatedValue varchar(100))
Insert Into @t 
Select 'Somalia,Vietnam,Honolulu,Spain' Union All 
Select 'apple,banana,guava,India,Australia,Smart,Bus' Union All
Select 'Mango'

望ましい出力

Id  Col1    Col2    Col3    Col4    Col5        Col6    Col7    
1   Somalia Vietnam Honolulu Spain  Null        Null    Null
2   apple   banana  guava   India   Australia   Smart   Bus
3   Mango   Null    Null    Null    Null        Null    Null

このクエリを実行するにはどうすればよいですか?

これまでの私の試み(この後、私は迷っています)

SELECT 
    X.id,
    X.CommaSeperatedValue,
    Y.splitdata 
FROM
 (
    SELECT *,
    CAST('<X>'+REPLACE(F.CommaSeperatedValue,',','</X><X>')+'</X>' AS XML) AS xmlfilter 
    FROM @t F
 )X
 CROSS APPLY
 ( 
    SELECT fdata.D.value('.','varchar(50)') as splitdata 
    FROM X.xmlfilter.nodes('X') as fdata(D)
 )Y

前もって感謝します

4

3 に答える 3

3

さて、ここにあなたが探している動的ソリューションがあります。一時テーブルを使用しました。これを永続テーブルまたはテーブル変数に置き換えることができます。

Declare @t table (Id int identity,CommaSeperatedValue varchar(100))
Insert Into @t 
Select 'Somalia,Vietnam' Union All 
Select 'apple,banana,guava,India,Australia'
IF object_ID('TempDB..#Temp') IS NOT NULL DROP TABLE #Temp;
SELECT 
X.id,
--X.CommaSeperatedValue,
Y.splitdata
,ROW_NUMBER() OVER( PARTITION  BY X.id ORDER BY X.id ) AS DataID
INTO #Temp 
FROM
 (
SELECT *,
CAST('<X>'+REPLACE(F.CommaSeperatedValue,',','</X><X>')+'</X>' AS XML) AS xmlfilter 
FROM @t F
 )X
 CROSS APPLY
 ( 
    SELECT fdata.D.value('.','varchar(50)') as splitdata 
    FROM X.xmlfilter.nodes('X') as fdata(D)
 )Y

DECLARE @MAXCol INT = (SELECT MAX(DataID)FROM #Temp)
     ,@index INT =1
     ,@ColNames varchar(4000)=''
     WHILE (@index<=@MAXCol)
     BEGIN 
     SET @ColNames =@ColNames +'MAX(CASE WHEN DataID = '+LTRIM(STR(@index))+' THEN splitdata END) as Col'+LTRIM(STR(@index))+','
     SET @Index=@Index +1        
     END
SET @ColNames = LEFT(@ColNames,LEN(@ColNames)-1) -- Remove Last Comma
EXECUTE   ( 'SELECT
        [id],'+@ColNames+' FROM #Temp GROUP BY [id]'
      )
于 2012-09-03T05:51:51.423 に答える
2

すでに取得したものを使用して、行番号を追加し、groupbyを使用して転置します。

SELECT
    [id],
    MAX(CASE WHEN RowNumber=1 THEN splitdata END) as Col1,
    MAX(CASE WHEN RowNumber=2 THEN splitdata END) as Col2,
    MAX(CASE WHEN RowNumber=3 THEN splitdata END) as Col3,
    MAX(CASE WHEN RowNumber=4 THEN splitdata END) as Col4,
    MAX(CASE WHEN RowNumber=5 THEN splitdata END) as Col5,
    MAX(CASE WHEN RowNumber=6 THEN splitdata END) as Col6,
    MAX(CASE WHEN RowNumber=7 THEN splitdata END) as Col7,
    MAX(CASE WHEN RowNumber=8 THEN splitdata END) as Col8,
    MAX(CASE WHEN RowNumber=9 THEN splitdata END) as Col9,
    MAX(CASE WHEN RowNumber=10 THEN splitdata END) as Col10

FROM (
    SELECT 
        X.id,
        Y.splitdata,
        ROW_NUMBER() OVER (PARTITION BY id ORDER BY id) AS RowNumber
    FROM
     (
        SELECT *,
        CAST('<X>'+REPLACE(F.CommaSeperatedValue,',','</X><X>')+'</X>' AS XML) AS xmlfilter 
        FROM @t F
     )X
     CROSS APPLY
     ( 
        SELECT fdata.D.value('.','varchar(50)') as splitdata 
        FROM X.xmlfilter.nodes('X') as fdata(D)
     )Y
) X
GROUP BY [id]

これにより、次のようになります。

id  Col1    Col2    Col3    Col4    Col5    Col6    Col7    Col8    Col9    Col10
1   Somalia Vietnam Honolulu    Spain   NULL    NULL    NULL    NULL    NULL    NULL
2   apple   banana  guava   India   Australia   Smart   Bus NULL    NULL    NULL
3   Mango   NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL    NULL
于 2012-09-03T05:28:12.727 に答える