首页 > 解决方案 > 带有基于文本的字段的 SQL 透视

问题描述

原谅我,但我不能让这个工作。我可以找到许多使用数值的复杂枢轴,但没有任何基本的基于字符串的基础。

假设这是我来自临时表的源查询。我无法改变这一点:

select * from @tmpTable

这提供了 12 行:

Row | Name           | Code
---------------------------------
1   | July 2019      | 19/20-01
2   | August 2019    | 19/20-02
3   | September 2019 | 19/20-03 
..  ..                 ..
12  | June 2020      | 19/20-12

我想对此进行旋转并返回如下数据:

    Data Type  |      [0]     |      [1]      |       [3]        |  [12]
---------------------------------------------------------------------------
    Name       |   July 2019  |  August 2019  | September 2019   |  June 2020
    Code       |   19/20-01   |  19/20-02     | 19/20-03         |  19/20-12

提前致谢..

标签: sqlselectpivot

解决方案


字符串和数字在数据透视方面没有太大区别,只是您不能在它们上使用像 SUM 或 AVG 这样的数字聚合器。MAX 会很好,在这种情况下,您将只有一个值,因此不会丢失任何内容

您需要先将数据拉出到更高的键/值表示形式,然后再将其转回以像现在一样反向查看

反透视数据:

WITH upiv AS(
   SELECT 'Name' as t, row as r, name as v FROM @tempTable
   UNION ALL
   SELECT 'Code' as t, row, code FROM @tempTable
)

现在可以在 r 列上重新分组和有条件地聚合数据:

SELECT
  t,
  MAX(CASE WHEN r = 1 THEN v END) as r1,
  MAX(CASE WHEN r = 2 THEN v END) as r2,
  ...
  MAX(CASE WHEN r = 12 THEN v END) as r12
FROM
  upiv
GROUP BY
  t

您需要将我在这里介绍的两个 sql 块放在一起,以便它们形成一个 sql 语句。如果您想了解更多关于它是如何工作的,我建议您在 with 块中运行 sql 语句,查看它,并从完整语句中删除 group by/max 单词并查看结果。您将看到 WITH 块查询使数据更高,本质上是一个跟踪数据类型(名称或代码)的键/值对。当您在没有 group by/max 的情况下运行完整的 sql 时,您会看到 tall 数据横向展开以提供大量空值和一组对角单元格数据(如果按 r 排序)。group by 折叠所有这些空值,因为 MAX 将选择任何值而不是空值(其中只有一个)

您也可以将其作为 UNPIVOT 后跟 PIVOT。我一直更喜欢使用这种形式,因为不是每个数据库都支持 UN/PIVOT 关键字。可以说,UNPIVOT/PIVOT 可以表现得更好,因为开发人员可以进行特定的优化(例如,UNPIVOT 可以单次扫描表;这种多重联合方法可能需要多次扫描,并且循环它的方式可能会占用更多内存),但在这种情况下,它是只有 12 行。我怀疑您使用的是 SQLServer,但如果您使用的是不理解 WITH 的数据库,您可以将 WITH(包括括号)的括号语句放在 theFROM和 the之间upiv,使其成为子查询(如果模式SELECT ... FROM (SELECT ... UNION ALL SELECT ...) upiv GROUP BY ...; 没有区别

我会将重命名输出列作为练习留给您,但我会敦促您考虑不要在问题中显示的列名中添加空格或方括号


推荐阅读