【问题标题】:Pivot or transpose a table in SQL Server without GROUPING BY在不使用 GROUPING BY 的情况下在 SQL Server 中透视或转置表
【发布时间】:2013-03-06 23:14:40
【问题描述】:

我需要在 SQL Server 中对具有以下结构的表进行透视:

CREATE TABLE table1 (
    ColumnNumber int,
    RowNumber int,
    CellData nvarchar(50)
)

INSERT INTO table1 VALUES
(1, 1, 'Orange'),
(2, 1, 'Apple'),
(3, 1, 'Banana'),
(1, 2, 'Grape'),
(2, 2, 'Corn'),
(3, 2, 'Lemon'),
(1, 3, 'Tomato'),
(2, 3, 'Lettuce'),
(3, 3, 'Onion')

我需要生成的表格如下所示:

所以ColumnNumber 行中的单元格现在是结果表的列名。最难的部分是不同列号的数量是可变的(所以现在,我们有 3 个列号,但明天可能有 6 个或 10 个)。

我一直在研究 PIVOT 函数,但所有示例都包含 GROUP BY,而且,正如您在此处看到的,我需要更像“转置”excel 函数的东西。

谢谢!!

【问题讨论】:

标签: sql-server pivot transpose


【解决方案1】:

这可以使用PIVOT 函数来完成。 GROUP BY 将起作用,因为您有一个使每一行都不同的指示器。对于您的数据,指标是rowNumber 列。

如果您有一定数量的列,那么您需要使用静态数据透视表对它们进行硬编码。代码将类似于以下内容:

select [1], [2], [3]
from
(
  select colNumber, RowNumber, CellData
  from yourtable
) src
pivot
(
  max(CellData)
  for colnumber in ([1], [2], [3])
) piv;

SQL Fiddle with Demo

在您的情况下,您声明您将拥有未知数量的列。如果这是您的情况,那么您将需要使用动态 sql 来构建要透视的列列表。我演示了静态版本,因为它更容易将代码转换为动态 SQL。

动态 sql 版本的关键是获取列列表,这是通过查询表并创建列名字符串来完成的。这是使用FOR XML PATH 完成的:

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(colNumber) 
                    from yourtable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

然后将此列表添加到您生成的查询字符串中,最终代码为:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(colNumber) 
                    from yourtable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT ' + @cols + ' 
             from 
             (
                select colNumber, rowNumber, CellData
                from yourtable
            ) x
            pivot 
            (
                min(CellData)
                for colNumber in (' + @cols + ')
            ) p '

execute(@query)

SQL Fiddle with Demo

两者都给出结果:

|      1 |       2 |      3 |
-----------------------------
| Orange |   Apple | Banana |
|  Grape |    Corn |  Lemon |
| Tomato | Lettuce |  Onion |

【讨论】:

  • @pst 我不明白你的评论。 bluefeet 回答了另一个关键问题。如果您注意到,他们真的似乎很喜欢这类问题,并提供全面、详细和正确的答案。
  • @bluefeet 虽然,为什么这里选择 MIN 而另一个选择 MAX?只是日常偏好还是会影响语义?
  • @pst 您可以使用minmax,因为聚合是在字符串上完成的。它们都会给出相同的结果。
  • 非常感谢,这正是我想要的。对不起,如果这是一个重复的问题,但我没有找到任何其他类似的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
相关资源
最近更新 更多