2

我有一些数据如下

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

CommaSeparated 值没有限制。提供的样本的期望输出将是

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

使用你已经得到的,添加一个行号,并使用 group by 转置它。

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 回答
0

我相信您需要使用动态 SQL 来执行此操作,因为该SELECT语句需要指定列数,或者您需要遍历 CSV 列中的项目数。

通常这是一个坏主意,会导致比它解决的问题更多的问题,并且对于下一个人来说太混乱而无法维护。您可能要考虑的只是将数据展平为两列格式

-- ie your initial data
1, 'Somalia,Vietnam,Honolulu,Spain'
2, 'apple,banana,guava,India,Australia,Smart,Bus'
3, 'Mango'

-- would become
1, 'Somalia'
1, 'Vietnam'
1, 'Honolulu'
1, 'Spain'
2, 'apple'
2, 'banana
-- etc 

现在在您的表示层中进行分组和旋转。

尝试在 SQL 中格式化数据(可能用于报告或数据导出?)是一个常见的错误,实际上只是尝试将日期存储为文字的一个错误。SQL 是一种数据存储和操作语言/平台;它不适用于数据 尝试以这种方式使用它只会让自己头疼不已。

于 2012-09-03T05:19:28.083 回答