PIVOT

功能概述

PIVOT
PIVOT
把行转为列:按指定列的取值生成新列,每个新列是对应取值的聚合结果。典型用法是把“月份 × 金额”的明细转成每个月一列的报表宽表。

PIVOT
PIVOT
等价于
GROUP BY
GROUP BY
加多个
CASE WHEN
CASE WHEN
条件聚合,但写法更短,新增透视值时只需改
IN
IN
列表。透视值不固定、需要动态生成列时,
PIVOT
PIVOT
无法满足,仍需拼接 SQL。反向操作(列转行)见 UNPIVOT。

语法

SELECT ... FROM <relation> PIVOT ( <aggregate_expr> [[AS] <agg_alias>] [, <aggregate_expr> [[AS] <agg_alias>] ...] FOR <pivot_column> IN (<value> [[AS] <value_alias>] [, ...]) ) [[AS] <alias>] -- 多列透视 PIVOT ( <aggregate_expr> [[AS] <agg_alias>] [, ...] FOR (<col1>, <col2> [, ...]) IN ((<v1>, <v2> [, ...]) [[AS] <value_alias>] [, ...]) )

参数说明

  • <relation>
    <relation>
    :输入的表、视图或子查询。除聚合用到的列和
    <pivot_column>
    <pivot_column>
    之外,其余列都自动作为分组列。

  • <aggregate_expr>
    <aggregate_expr>
    :聚合表达式,如
    sum(earnings)
    sum(earnings)
    、
    avg(earnings)
    avg(earnings)
    、
    sum(earnings * s)
    sum(earnings * s)
    。可以写多个,每个透视值会生成多列。必须是聚合函数,不能是
    abs(earnings)
    abs(earnings)
    这类普通表达式;不能嵌套聚合。

  • <agg_alias>
    <agg_alias>
    :可选,聚合表达式的别名,用于生成列名。

  • <pivot_column>
    <pivot_column>
    :要按取值展开为列的列。多列透视时写作
    (<col1>, <col2>)
    (<col1>, <col2>)
    。

  • <value>
    <value>
    :要展开的取值,必须是常量。多列透视时写作
    (<v1>, <v2>)
    (<v1>, <v2>)
    ,个数必须与 FOR 中的列数一致。不在
    IN
    IN
    列表中的取值被忽略。

  • <value_alias>
    <value_alias>
    :可选,透视值的别名,用于生成列名。

生成的列名规则:

情况列名示例
一个聚合、无别名透视值
dotNET
dotNET
、
Java
Java
多个聚合
<透视值>_<聚合别名或表达式>
<透视值>_<聚合别名或表达式>
2012_s
2012_s
、
2013_a
2013_a
透视值有别名用别名代替透视值
firstYear_s
firstYear_s

使用示例

前置数据:

CREATE OR REPLACE VIEW doc_course_sales AS SELECT * FROM VALUES ('dotNET', 2012, 10000), ('Java', 2012, 20000), ('dotNET', 2012, 5000), ('dotNET', 2013, 48000), ('Java', 2013, 30000) AS t(course, year, earnings);

按课程展开,每年一行:

SELECT * FROM ( SELECT year, course, earnings FROM doc_course_sales ) PIVOT ( sum(earnings) FOR course IN ('dotNET', 'Java') ) ORDER BY year;

yeardotNETJava
20121500020000
20134800030000

year
year
没有出现在聚合和 FOR 中,自动成为分组列。

多个聚合,并为聚合和透视值设置别名:

SELECT * FROM ( SELECT year y, course c, earnings e FROM doc_course_sales ) PIVOT ( sum(e) s, avg(e) a FOR y IN (2012 AS first_year, 2013 AS second_year) ) ORDER BY c;

cfirst_year_sfirst_year_asecond_year_ssecond_year_a
Java2000020000.03000030000.0
dotNET150007500.04800048000.0

avg
avg
的结果是 DOUBLE,带小数点。

多列透视,按“课程 + 年份”的组合展开:

SELECT * FROM ( SELECT course, year, earnings FROM doc_course_sales ) PIVOT ( sum(earnings) FOR (course, year) IN (('dotNET', 2012) AS dotnet_2012, ('Java', 2013) AS java_2013) );

dotnet_2012java_2013
1500030000

注意事项

  • 透视值必须是常量,不支持子查询或动态列表。
  • 除聚合列和透视列外的所有输入列都会成为分组列,建议先用子查询裁剪列。
  • 聚合表达式必须是聚合函数,不能嵌套聚合。
  • MAP 类型的列不能作为透视列。

相关文档

联系我们
预约咨询
微信咨询
电话咨询
邮件咨询