【问题标题】:Pivot multiple columns over one column in SQL Server在 SQL Server 中将多列透视到一列
【发布时间】:2019-05-08 21:00:32
【问题描述】:

我有一个名为 #rdata 的临时表,如下所示:

Months      KPI_1       KP1_2        KPI_3   
-------------------------------------------
Jan-18       x            x            x 
Feb-18       x            x            x 
Mar-18       x            x            x 
Apr-18       x            x            x 
Aug-18       x            x            x 

我想改成这张表:

 KPIs      Jan-18     Feb-18      Mar-18 ....
 -------------------------------------------
 KPI_1       x            x            x 
 KPI_2       x            x            x 
 KPI_3       x            x            x 

我已经走到这一步了:

 ----Creating a list of Months  

    SELECT @Columns =   COALESCE(@Columns + ', ','') + QUOTENAME(Months)
     FROM
    (SELECT DISTINCT Months
      FROM  #rdata ) AS B



  SET @SQL = 'SELECT  ' + @Columns + ' KPI_1, KPI_2,KPI_3 FROM #rdata
  ) as PivotData

  PIVOT
  (
    FOR Months IN (' + @Columns + ')
   ) AS PivotResult'
   EXEC(@SQL)

它似乎不起作用,知道我错过了什么吗?

【问题讨论】:

  • 您收到错误消息吗?打印出来的 SQL 是什么样子的?
  • ...在数据库中进行透视也是一个好主意。透视通常用于表示目的,并且在表示层中处理得更好。我个人不会为此使用 PIVOT。相反,我会使用交叉连接来获取行上的 KPI,并使用 CASE WHEN / GROUP BY 来转向列
  • @Nick.McDermaid..仅供参考The syntax for PIVOT provides is simpler and more readable than the syntax that may otherwise be specified in a complex series of SELECT...CASE statements.From microsoft.com

标签: sql-server tsql pivot dynamic-sql unpivot


【解决方案1】:

只需执行UNPIVOT,然后执行PIVOT。这是完整的工作示例:

DROP TABLE IF EXISTS #rdata;

CREATE TABLE #rdata
(
    [Months] VARCHAR(12)
   ,[KPI_1] INT
   ,[KPI_2] INT
   ,[KPI_3] INT
);

INSERT INTO #rdata ([Months], [KPI_1], [KPI_2], [KPI_3])
VALUES ('Jan-18 ', 1, 2, 3)
      ,('Feb-18 ', 4, 5, 6)
      ,('Mar-18 ', 7, 8, 9)
      ,('Apr-18 ', 10, 11, 12)
      ,('Aug-18 ', 13, 14, 15)


DECLARE @DynammicTSQLStatement NVARCHAR(MAX)
       ,@DynamicPIVOTColumns NVARCHAR(MAX);


SET @DynamicPIVOTColumns = STUFF
                          (
                                (
                                SELECT ',[' + CAST([Months] AS VARCHAR(12)) + ']'
                                FROM #rdata
                                GROUP BY [Months]
                                ORDER BY [Months]
                                FOR XML PATH('') ,TYPE
                                ).value('.', 'NVARCHAR(MAX)')
                                ,1
                                ,1
                                ,''
                          );

SET @DynammicTSQLStatement = N'
SELECT *
FROM #rdata
UNPIVOT
(
    [value] FOR [KPIs] IN ([KPI_1], [KPI_2], [KPI_3])
) UNPVT
PIVOT
(
    MAX([value]) FOR [Months] IN (' + @DynamicPIVOTColumns + ')
) PVT'


EXEC sp_executesql @DynammicTSQLStatement;

请注意,当我根据月份列创建动态列时,我是按月份值本身排序的。如果您想按时间顺序对月份进行排序,则需要以不同的格式(如 2018-01、2017-10)存储数据,以便按其他列(如主键或类似的东西)排序。

【讨论】:

  • KPI 是否必须全部为同一类型?一个是int,其他是十进制。我收到此错误:与 UNPIVOT 列表中指定的其他列的类型冲突
  • 是的,您需要将它们转换成字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多