Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何制作动态柱_Sql_Sql Server_Tsql_Sql Server 2005 - Fatal编程技术网

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]'
      )