想学习架构师构建流程请跳转:Java架构师系统架构设计
select explode((11,22,33)) as item;
1.3.1 业务需求
有一份数据《The_NBA_Championship.txt》,关于部分年份的NBA总冠军球队名单:
1.3.2 代码实现
1.3.3 explode使用限制
在select条件中,如果只有explode函数表达式,程序执行是没有任何问题的;
但是如果在select条件中,包含explode和其他字段,就会报错。错误信息为:
org.apache.hadoop.hive.ql.parse.SemanticException:UDTF’s are not supported outside the SELECT clause, nor nested in expressions
那么如何理解这个错误呢?为什么在select的时候,explode的旁边不支持其他字段的同时出现?
1.3.4 explode语法限制原因
Lateral View是一种特殊的语法,主要用于搭配UDTF类型功能的函数一起使用,用于解决UDTF函数的一些查询限制的问题。
侧视图的原理是将UDTF的结果构建成一个类似于视图的表,然后将原表中的每一行和UDTF函数输出的每一行进行连接,生成一张新的虚拟表。这样就避免了UDTF的使用限制问题。使用lateral view时也可以对UDTF产生的记录设置字段名称,产生的字段可以用于group by、order by 、limit等语句中,不需要再单独嵌套一层子查询。
一般只要使用UDTF,就会固定搭配lateral view使用。
官方链接:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+LateralView
针对上述NBA冠军球队年份排名案例,使用explode函数+lateral view侧视图,可以完美解决:
–lateral view侧视图基本语法如下
select …… from tabelA lateral view UDTF(xxx) 别名 as col1,col2,col3……;
select a.team_name ,b.year
from the_nba_championship a lateral view explode(champion_year) b as year
–根据年份倒序排序
select a.team_name ,b.year
from the_nba_championship a lateral view explode(champion_year) b as year
order by b.year desc;
HQL提供了几种内置的UDAF聚合函数,例如max(…),min(…)和avg(…)。这些我们把它称之为基础的聚合函数。
通常情况下,聚合函数会与GROUP BY子句一起使用。 如果未指定GROUP BY子句,默认情况下,它会汇总所有行数据。
3.2.1 概述与表数据环境准备
3.2.2 Grouping sets
grouping sets是一种将多个group by逻辑写在一个sql语句中的便利写法。
等价于将不同维度的GROUP BY结果集进行UNION ALL。
GROUPING__ID表示结果属于哪一个分组集合。
3.2.3 Cube
cube的语法功能指的是:根据GROUP BY的维度的所有组合进行聚合。
对于cube,如果有n个维度,则所有组合的总个数是:2^n。
比如Cube有a,b,c3个维度,则所有组合情况是:
((a,b,c),(a,b),(b,c),(a,c),(a),(b),©,())。
3.2.4 Rollup
cube的语法功能指的是:根据GROUP BY的维度的所有组合进行聚合。
rollup是Cube的子集,以最左侧的维度为主,从该维度进行层级聚合。
比如ROLLUP有a,b,c3个维度,则所有组合情况是:
((a,b,c),(a,b),(a),())。
4.3.1 窗口聚合函数
从Hive v2.2.0开始,支持DISTINCT与窗口函数中的聚合函数一起使用。
这里以sum()函数为例,其他聚合函数使用类似。
4.3.2 窗口表达式
我们知道,在sum(…) over( partition by… order by … )语法完整的情况下,进行的累积聚合操作,默认累积聚合行为是:从第一行聚合到当前行。
Window expression窗口表达式给我们提供了一种控制行范围的能力,比如向前2行,向后3行。
语法如下:
关键字是rows between,包括下面这几个选项
4.3.3 窗口排序函数
窗口排序函数用于给每个分组内的数据打上排序的标号。注意窗口排序函数不支持窗口表达式。总共有4个函数需要掌握:
row_number:在每个分组中,为每行分配一个从1开始的唯一序列号,递增,不考虑重复;
rank: 在每个分组中,为每行分配一个从1开始的序列号,考虑重复,挤占后续位置;
dense_rank: 在每个分组中,为每行分配一个从1开始的序列号,考虑重复,不挤占后续位置;
4.3.4 窗口分析函数
LAG(col,n,DEFAULT) 用于统计窗口内往上第n行值
第一个参数为列名,第二个参数为往上第n行(可选,默认为1),第三个参数为默认值(当往上第n行为NULL时候,取默认值,如不指定,则为NULL);
LEAD(col,n,DEFAULT) 用于统计窗口内往下第n行值
第一个参数为列名,第二个参数为往下第n行(可选,默认为1),第三个参数为默认值(当往下第n行为NULL时候,取默认值,如不指定,则为NULL);
FIRST_VALUE 取分组内排序后,截止到当前行,第一个值;
LAST_VALUE 取分组内排序后,截止到当前行,最后一个值;
随机抽样使用rand()函数和LIMIT关键字来获取数据。 使用了DISTRIBUTE和SORT关键字,可以确保数据也随机分布在mapper和reducer之间,使得底层执行有效率。
ORDER BY 和rand()语句也可以达到相同的目的,但是表现不好。因为ORDER BY是全局排序,只会启动运行一个Reducer。
Block块采样允许select随机获取n行数据,即数据大小或n个字节的数据。
采样粒度是HDFS块大小。
这是一种特殊的采样方法,针对分桶表进行了优化。