sql - 在 SQL Server 2008 R2 中使用 PIVOT 表

标签 sql sql-server-2008-r2 pivot

我遇到了一个无法解决的问题,并已尝试了所有方法。希望我能在这里得到答案。

我的表中的数据如下

Id Month Val1 Val2 Val3
1  Jan   70   80   90
2  Jan   12   13   15
3  Feb   12   67   99
4  March 14   15   17.1

从以下结构中,我想根据列 val1 透视数据所以我的输出看起来像:
Jan Jan Feb March
70  12  12  14

最佳答案

您将需要使用我原以为的动态 SQL(除非您的列将保持静态)

需要执行的查询是:

SELECT  [Jan] = [Jan1], 
        [Jan] = [Jan2], 
        [Feb] = [Feb1], 
        [March] = [March1]
FROM    (   SELECT  [PivotColumn] = [Month] + CONVERT(VARCHAR(10), ROW_NUMBER() OVER(PARTITION BY [Month] ORDER BY ID)), 
                    Val1
            FROM    T
        ) t
        PIVOT
        (   MAX(Val1)
            FOR [PivotColumn] IN ([Jan1], [Jan2], [Feb1], [March1])
        ) pvt

虽然我不确定为什么会这样
Jan Jan Feb March
70  12  12  14

并不是
Jan Jan Feb March
12  70  12  14

所以你可能需要修改 ORDER BYROW_NUMBER功能。

要动态构建它,您可以使用:
-- CREATE SAMPLE TABLE AND INSERT DATA
CREATE TABLE #T (ID INT, Month VARCHAR(10), Val1 INT, Val2 INT, Val3 DECIMAL(5, 1));
INSERT #T VALUES (1, 'Jan', 70, 80, 90), (2, 'Jan', 12, 13, 15), (3, 'Feb', 12, 67, 99), (4, 'March', 14, 15, 17.1);

-- DECLARE VARIABLES TO STORE THE COLUMN NAMES
DECLARE @PivotList NVARCHAR(MAX) = '',
        @ColumnList NVARCHAR(MAX) = '';

-- HERE USE ROW_NUMBER() TO UNIQUELY IDENTIFY VALUES FOR MONTHS 
-- THIS MEANS JAN: 70 AND JAN: 12 CAN BE IDENTIFIED SEPARATELY LATER, BUT RETAIN THE DUPLICATE COLUMN NAME [Jan]
SELECT  @ColumnList = @ColumnList + ', ' + QUOTENAME([Month]) + ' = ' + QUOTENAME([Month] + CONVERT(VARCHAR(10), ROW_NUMBER() OVER(PARTITION BY [Month] ORDER BY ID))),
        @PivotList = @PivotList + ', ' + QUOTENAME([Month] + CONVERT(VARCHAR(10), ROW_NUMBER() OVER(PARTITION BY [Month] ORDER BY ID)))
FROM    #T
ORDER BY ID;

DECLARE @SQL NVARCHAR(MAX) = 'SELECT ' + STUFF(@ColumnList, 1, 2, '') + '
                            FROM    (   SELECT  [PivotColumn] = [Month] + CONVERT(VARCHAR(10), ROW_NUMBER() OVER(PARTITION BY [Month] ORDER BY ID)), 
                                                Val1
                                        FROM    #T
                                    ) t
                                    PIVOT
                                    (   MAX(Val1)
                                        FOR [PivotColumn] IN (' + STUFF(@PivotList, 1, 2, '') + ')
                                    ) pvt';

EXECUTE SP_EXECUTESQL @SQL;

DROP TABLE #T;

再次在 ROW_NUMBER 中进行任何更改还需要反射(reflect)在 ORDER BY 中生成列名称和数据透视表的查询中的子句:
SELECT  @ColumnList = @ColumnList + ', ' + QUOTENAME([Month]) + ' = ' + QUOTENAME([Month] + CONVERT(VARCHAR(10), ROW_NUMBER() OVER(PARTITION BY [Month] ORDER BY ID))),
        @PivotList = @PivotList + ', ' + QUOTENAME([Month] + CONVERT(VARCHAR(10), ROW_NUMBER() OVER(PARTITION BY [Month] ORDER BY ID)))
FROM    #T
ORDER BY ID;

关于sql - 在 SQL Server 2008 R2 中使用 PIVOT 表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13011350/

相关文章:

c# - 在 spid = -2 的 sql server 2008 R2 上运行的进程

sql-server - 提取大写字母和数字

mysql - 如何在 MySQL 中返回数据透视表输出?

php - Mysql/PHP/Smarty - 如何在一行中检索 2 个不同的行集?

mysql - 获取 MySQL 中的最后一行

mysql - 当我们有复合索引时是否需要正常的 MySql 索引

mysql - SQL 查询从表中检索下一个可用 ID

MySQL:我有一些主键问题

sql - 没有交叉连接的未售出产品查询?

r - 将 R 列值扩展为具有另一列值的列标题