我有
下的一些数据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
提前致谢
答案 0 :(得分:3)
这里是你正在寻找的动态解决方案。我使用Temp Table你可以用永久表或表变量替换它。
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]'
)
答案 1 :(得分:2)
使用您已经获得的内容,添加一个行号,并使用分组转换它。
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
答案 2 :(得分: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是一种数据存储和操作语言/平台;它不适用于数据尝试以这种方式使用它只会让自己无法忍受头疼。