深入 MaxCompute - 第十二弹 -PIVOT/UNPIVOT
简介: MaxCompute 推出新语法 - PIVOT/UNPIVOT:通过 PIVOT 关键字基于聚合将一个或者多个指定值的行转换为列;通过 UNPIVOT 关键字可将一个或者多个列转换为行。以更简洁易用的方式满足行转列和列转行的需求,简化了查询语句,提高了广大大数据开发者的生产力。
MaxCompute(原 ODPS)是阿里云自主研发的具有业界领先水平的分布式大数据处理平台, 尤其在集团内部得到广泛应用,支撑了多个 BU 的核心业务。MaxCompute 除了持续优化性能外,也致力于提升 SQL 语言的用户体验和表达能力,提高广大 MaxCompute 开发者的生产力。
MaxCompute 基于 MaxCompute2.0 新一代的 SQL 引擎,显著提升了 SQL 语言编译过程的易用性与语言的表达能力。我们在此推出深入 MaxCompute 系列文章
第一弹 - 善用MaxCompute编译器的错误和警告
第二弹 - 新的基本数据类型与内建函数
第三弹 - 复杂类型
第四弹 - CTE,VALUES,SEMIJOIN
第五弹 - SELECT TRANSFORM
第六弹 - User Defined Type
第七弹 - Grouping Set, Cube and Rollup
第八弹 - 动态类型函数
第九弹 - 脚本模式与参数视图
第十弹 - IF ELSE分支语句
第十一弹 - QUALIFY
本文将向您介绍 MaxCompute 支持的新语法 - PIVOT/UNPIVOT,即通过 PIVOT 关键字基于聚合将一个或者多个指定值的行转换为列;通过 UNPIVOT 关键字可将一个或者多个列转换为行。常见的场景入下:
场景 1
某个业务表,需要把表中的值当做新的列,并且根据每个值聚合现有的结果,从而实现行转列的效果。在没有支持 PIVOT 前,要实现这个需求,需要结合 GROUP BY 语法+聚合函数+Filter 语法过滤来实现。
场景 2
某个业务表,需要构造一个新的列,把原有的几个列名合并在这个列里面,并且用另一个新列来放置原来几个列的值,从而实现列转行的效果。在没有支持 UNPIVOT 前,要实现这个需求,需要结合 CROSS JOIN 语法+CASE WHEN 表达式来构造实现。
PIVOT/UNPIVOT 功能
PIVOT
PIVOT 概述
PIVOT 语法将指定的行旋转为多列,并且对其余列值聚合得到结果并旋转表。PIVOT 语法是 FROM 子句的一部分。
<aggregate_function>
表示行转列时需要计算的聚合函数,且聚合函数的外层不能嵌套任何函数,可以是 Scalar 函数和列组成的表达式。同时聚合函数的参数内部不能有其他聚合函数、Window 函数,以及聚合函数的列只能是上游表中的列。
<alias>
表示行转列时需要计算的聚合函数的对应列的别名。
<column>
表示行转列的对应行的列名,不能是任何的表达式。
<value>
表示行转列的对应行的值,也可以是表达式,但是不允许有任何的聚合函数和窗口函数,并且每一个元组内的元素数量要与<column>数量一致。
<new_column>
表示行转列后新的列的别名,不指定别名时,会试图推测别名,推测失败会由系统自动生成一个别名。
更详细的语法使用说明可参考文档。
PIVOT 语法可以等效为 group by + aggregate function + filter 的结合。以下面这个例子为例
上面的语法等效于
其中 FROM 内的表是 PIVOT 上游的结果,k1, ... kN 是所有未在 agg1, agg2, ...和 axis1, ..., axisN 出现的列的集合。
PVIOT 示例
数据准备。以下表代表几家连锁店对应物品在对应年份的销售情况。
统计各个年份各个店对物品的卖出数量情况。
没有支持 PVIOT 语法前,实现如下:
通过 PVIOT 语法实现如下:
可以在此时为聚合函数和新的列起别名,列名根据下划线合并:
计算每个物品每家商店每年的总卖出数量和最高销售额,通过 PIVOT 实现如下:
只计算 shop1 在 2020 年和 2021 对于每件物品的总卖出数量和最高销售额,通过 PIVOT 实现如下:
UNPIVOT
UNPIVOT 概述
UNPIVOT 语法通过将列转换为行来旋转表格,UNPIVOT 语法是 FROM 子句的一部分。
[EXCLUDE NULLS]
若指定该语法,则会过滤掉所有都是 null 的行。
<new_column_of_name>
列转行以后用于存储原有的列名的列,必须为列名不能是表达式也不能重名。数量需要和每一个<column value>元祖内部元素的数量相同,其中<column value>不指定时,MaxCompute 会自动生成一组 string 类型的元祖。
<new_column_of_value>
列转行以后用于存储原有的列对应值的列,必须为列名不能是表达式也不能重名,数量需要和每一个<column>元祖内部元素的数量相同。
<column>
用于列转行的原有的列。
<column_value>
用于列转行的原有的列的别名,可以用于替换原有的列名,内部不允许有列名。
更详细的语法使用说明可参考文档。
UNPIVOT 语法可以等效为 CROSS JOIN + CASE WHEN 表达式的结合。以下面这个例子为例:
上面的语法等效于
UNPIVOT 示例
数据准备。以下表代表几家连锁店对应物品在对应年份的销售情况:
旋转表,得到各个商店的销售数量,并且用新的列名 count 来替代。
没有 UNPIVOT 前的实现方式:
通过 UNPIVOT 实现:
如果 shop1 和 shop2 是东区商店,shop3 和 shop4 是西区商店,接下来需要一个新的列表示东区商店和西区商店。其中 count1 和 count2 两列分别存储了两店的销售数量。
别名可以是多列,但是对应的需要生成的新的列名要相应增加:
小结
PIVOT/UNPIVOT 语法,以更简洁易用的方式满足行转列和列转行的需求,简化了查询语句,提高了广大大数据开发者的生产力。
版权声明: 本文为 InfoQ 作者【阿里云大数据AI技术】的原创文章。
原文链接:【http://xie.infoq.cn/article/d8d514493972ef9418d343e62】。文章转载请联系作者。
评论