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>
之外,其余列都自动作为分组列。
⚠️ 注意:输入中多余的列会被当成分组列,导致结果行数变多。建议先用子查询只选出需要的列,如
FROM (SELECT year, course, earnings FROM t) PIVOT (...)
FROM (SELECT year, course, earnings FROM t) PIVOT (...)
。
<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;
year
dotNET
Java
2012
15000
20000
2013
48000
30000
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;
c
first_year_s
first_year_a
second_year_s
second_year_a
Java
20000
20000.0
30000
30000.0
dotNET
15000
7500.0
48000
48000.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)
);