【问题标题】:change columns to rows将列更改为行
【发布时间】:2014-04-08 19:07:17
【问题描述】:

我有一个动态生成的表,我需要将所有列更改为行

所以我的桌子看起来像这样

Conv1 | Conv2 | ...
data1 | data2 | ...
data1 | data2 | ...
data1 | data2 | ...
 ...  |  ...  | ...

因为它是动态的,所以如果不运行 Select count(*) 或类似的东西,我不知道有多少行/列。

基本上我想把上表改成这个

data1 | data1 | data1 | ...
data2 | data2 | data2 | ...
data3 | data3 | data3 | ...
data4 | data4 | data4 | ...

我曾考虑使用Pivot,但我不确定在这种情况下我将如何使用它。

我正在使用 SQL Server 2008 R2

任何帮助将不胜感激。如果您需要更多信息,请告诉我。

谢谢。

--更新

这是当前的表结构,其中“Conv”项作为列名。

Conv1 | Conv2 | Conv3 | ...
data1 | data2 | data3 | ...
data1 | data2 | data3 | ...
data1 | data2 | data3 | ...
 ...  |  ...  |  ...  | ...

“数据”片段在哪里varchar(250)

将数据视为对话存储库 (Conv1),行是一系列问题和响应。 由于我必须处理的内容的性质,我不知道哪些“数据”内容是问题,哪些是响应。

这就是我想要的结果:

        Col1  | Col2  | Col3  | ...
Conv1 | data1 | data1 | data1 | ...
Conv2 | data2 | data2 | data2 | ...
Conv3 | data3 | data3 | data3 | ...
Conv4 | data4 | data4 | data4 | ...

如果这些信息还不够,请告诉我,我会看看还能提供什么。

【问题讨论】:

  • 这是执行动态数据透视的方法:stackoverflow.com/a/11985946/3503205
  • 我不明白我会用什么来代替@Ryx5 评论中的min(choice) 或@lyosha 评论中的max(val)。或者真的就此而言,Pivot 部分会是什么。在所有示例中,我看到原始表中包含具有特定内容的列,在我的情况下,这些列包含基本上几乎相同类型的数据,它们没有真正的区别特征。
  • 我会假设使用Pivot 不是答案,因为我认为我真的没有任何可以“聚合”的东西,据我慢慢理解,这对于@ 来说是必要的987654335@上班。还有其他方法可以将列转置为行吗?
  • 我想我只是将内容转储到 Excel 文件中并使用它的“转置”功能。

标签: sql sql-server pivot


【解决方案1】:

您正在尝试做的是一个完整的数据转置,其中您当前的数据列变成行并且您的行变成列,这可以分两步完成。首先,应用 UNPIVOT 函数将您当前的 Conv1Conv2 等列转换为行,然后应用 PIVOT 函数将data1data2 转换为列。

在尝试编写查询的动态版本之前,我总是从静态版本开始,这样可以获得正确的逻辑,然后转换为动态 sql。为了生成新的列名Col1Col2 等,我会在查询数据时使用像row_number() 这样的窗口函数,这将为您想要转置的每一行数据生成一个唯一的序列。

UNPIVOT 代码类似于:

;with cte as
(
    select Conv1, Conv2, Conv3,
        row_number() over(order by conv1) seq
    from dbo.yourtable
)
select * 
from 
(
    select Conv, value, 
        col = 'Col'+cast(seq as varchar(50))
    from cte
    unpivot
    (
        value for Conv in (Conv1, Conv2, Conv3)
    ) unpiv
) src;

SQL Fiddle with Demo。数据将如下所示:

|  CONV | VALUE |  COL |
|-------|-------|------|
| Conv1 | data1 | Col1 |
| Conv2 | data2 | Col1 |
| Conv3 | data3 | Col1 |
| Conv1 | data1 | Col2 |
| Conv2 | data2 | Col2 |
| Conv3 | data3 | Col2 |

您会注意到现在每个Conv1 都有多行,并且您有一个新列,其中使用row_number() 创建新列名。现在您可以使用 PIVOT 完成数据的旋转:

;with cte as
(
    select Conv1, Conv2, Conv3,
        row_number() over(order by conv1) seq
    from dbo.yourtable
)
select Conv, Col1, Col2, Col3
from 
(
    select Conv, value, 
        col = 'Col'+cast(seq as varchar(50))
    from cte
    unpivot
    (
        value for Conv in (Conv1, Conv2, Conv3)
    ) unpiv
) src
pivot
(
    max(value)
    for col in (Col1, Col2, Col3)
) piv;

SQL Fiddle with Demo。这会将您当前的数据完全转换为您的最终结果。对于您的情况,您说您需要一个动态解决方案,因此您需要使用动态 SQL。这将涉及获取需要取消透视的列名列表,然后获取透视的新列:

DECLARE @colsUnpivot AS NVARCHAR(MAX),
    @colsPivot AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @colsUnpivot = STUFF((SELECT ','+ quotename(c.name)
                    from sys.tables t
                    inner join sys.columns c
                        on t.object_id = c.object_id
                    where t.name = 'yourtable'
                    group by c.name, c.column_id
                    order by c.column_id
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colsPivot = STUFF((SELECT ','+ quotename('Col'+cast(seq as varchar(10)))
                   from
                   (
                    select row_number() over(order by conv1) seq
                    from dbo.yourtable
                   ) d
                   group by seq
                   order by seq
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query 
  = ';with cte as
    (
        select Conv1, Conv2, Conv3,
            row_number() over(order by conv1) seq
        from dbo.yourtable
    )
    select Conv, '+@colsPivot+'
    from 
    (
        select Conv, value, 
            col = ''Col''+cast(seq as varchar(50))
        from cte
        unpivot
        (
            value for Conv in ('+@colsUnpivot+')
        ) unpiv
    ) src
    pivot
    (
        max(value)
        for col in ('+@colsPivot+')
    ) piv'

execute sp_executesql @query;

SQL Fiddle with Demo。两者都给出了最终结果:

|  CONV |  COL1 |  COL2 |  COL3 |
|-------|-------|-------|-------|
| Conv1 | data1 | data1 | data1 |
| Conv2 | data2 | data2 | data2 |
| Conv3 | data3 | data3 | data3 |

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-14
    • 2013-10-18
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多