MS SQL Pivot动态标头

时间:2017-10-26 14:42:29

标签: sql sql-server tsql ssms

我有以下两个表:

Serial  Key     Value
ABC     Attr1   ABC1
ABC     Attr2   ABC2
ABC     Attr3   ABC3
XYZ     Attr1   XYZ1
XYZ     Attr2   XYZ2
XYZ     Attr3   XYZ3

Key     Include IncludeOrder
Attr1   Y       2
Attr2   NULL    NULL
Attr3   Y       1

第一个表是数据,第二个表是要包含在报告中的数据Key

我想从查询中生成以下内容:

Serial  Attr3   Attr1
ABC     ABC3    ABC1
XYZ     XYZ3    XYZ1

我知道这需要一个支点,GROUP BY上有Serial,但我无法完成子查询以提取Include指定的列或将它们排序为IncludeOrder在输出中正确排序。

1 个答案:

答案 0 :(得分:2)

使用dynamic-SQL很容易实现:

DECLARE @sql NVARCHAR(MAX)= 'SELECT Serial, <cols> FROM t GROUP BY Serial;';

DECLARE @cols NVARCHAR(MAX);
SELECT @cols = STRING_AGG(CONCAT('MIN(CASE WHEN [key] = ''',
                      [key],
                       ''' THEN [value] END) AS ',
                       QUOTENAME([key])),
                       ',') WITHIN GROUP (ORDER BY IncludeOrder)
FROM r
WHERE Include = 'Y';

SET @sql = REPLACE(@sql, '<cols>', @cols);

SELECT @sql;
EXEC(@sql);

输出查询:

SELECT Serial,
       MIN(CASE WHEN [key] = 'Attr3' THEN [value] END) AS [Attr3],
       MIN(CASE WHEN [key] = 'Attr1' THEN [value] END) AS [Attr1] 
FROM t 
GROUP BY Serial;

<强> DBFiddle Demo

注意:

  • SQL Server 2017及更高版本(由于STRING_AGG,可以随意将其重写为XML+STUFF version
  • 使用MIN
  • 进行条件汇总