Sql 如何制作动态柱
我有一些数据如下Sql 如何制作动态柱,sql,sql-server,tsql,sql-server-2005,Sql,Sql Server,Tsql,Sql Server 2005,我有一些数据如下 Declare @t table (Id int identity,CommaSeperatedValue varchar(100)) Insert Into @t Select 'Somalia,Vietnam' Union All Select 'apple,banana,guava,India,Australia' CommaseOperated值没有限制。所提供样品的预期输出为: Id Col1 Col2 Col3 Col4 Col5 1
Declare @t table (Id int identity,CommaSeperatedValue varchar(100))
Insert Into @t
Select 'Somalia,Vietnam' Union All
Select 'apple,banana,guava,India,Australia'
CommaseOperated值没有限制。所提供样品的预期输出为:
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
提前感谢我相信您需要使用动态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是一种数据存储和操作语言/平台;它不是为数据而设计的,试图以这种方式使用它只会让你头痛不已。按照你已经得到的,添加一个行号,并使用分组方式进行转换
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]
这是您正在寻找的动态解决方案。我使用了临时表,您可以用永久表或表变量替换它
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]'
)
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]'
)