本文首发于:大数据每日哔哔-Hive 分析函数
应用场景
(1)用于分区排序
(2)Top N
(3)层次查询
常用分析函数
| 分析函数 | 描述 |
|---|---|
| RANK | 返回数据项在分区中的排名。排名值序列可能会有间隔 |
| DENSE_RANK | 返回数据项在分区中的排名。排名值序列是连续的,没有间隔 |
| PERCENT_RANK | 计算当前行的百分比排名:(x - 1)/(窗口分区中的行数 - 1) |
| CUME_DIST | 统计小于或等于当前值的行数占总行数的比例: x/分区行数 |
| ROW_NUMBER | 确认分区中当前行的序号 |
| NTILE | 将每个分区的行尽可能均匀地划分为指定数量的分组 |
语法:analytics_functions over() clause
准备了一个表,用于测试:
create table test.gid_pv(gid string comment '商品ID',dt string comment '日期',pv string comment '访问次数') comment '商品访问次数'row format delimitedfields terminated by ','collection items terminated by '\n'stored as textfile;
数据如下:
0006D2BC-4DF9-4C0B-83AD-0183789E78D4 2020-01-10 10006D2BC-4DF9-4C0B-83AD-0183789E78D4 2020-01-11 50006D2BC-4DF9-4C0B-83AD-0183789E78D4 2020-01-12 70006D2BC-4DF9-4C0B-83AD-0183789E78D4 2020-01-13 30006D2BC-4DF9-4C0B-83AD-0183789E78D4 2020-01-14 20006D2BC-4DF9-4C0B-83AD-0183789E78D4 2020-01-15 40006D2BC-4DF9-4C0B-83AD-0183789E78D4 2020-01-16 4993BD7AD-3B62-BA0C-15AE-A14B85921889 2020-01-10 2993BD7AD-3B62-BA0C-15AE-A14B85921889 2020-01-11 9993BD7AD-3B62-BA0C-15AE-A14B85921889 2020-01-12 3993BD7AD-3B62-BA0C-15AE-A14B85921889 2020-01-13 1993BD7AD-3B62-BA0C-15AE-A14B85921889 2020-01-14 1993BD7AD-3B62-BA0C-15AE-A14B85921889 2020-01-15 8993BD7AD-3B62-BA0C-15AE-A14B85921889 2020-01-16 2
RANK函数会返回数据项在分区中的排名。OVER子句中的ORDER BY语句来确定根据哪个值进行排名。如果多行中的排序值相同,则会有相同的排名。如果有排名相同的情况下,则会在名次中留下空位。例如,如果两行排名为3,则下一个排名为5。DENSE_RANK()不会出现这种情况,具体可以对比一下
selectgid,dt,pv,rank() over (partition by gid order by pv desc) as pre_total_pv_rank,dense_rank() over (partition by gid order by pv desc) as pre_total_pv_dense_rankfrom test.gid_pvorder bygid,dt;


上面的两个是排序函数,如果只想给当前行编个号呢?
selectgid,dt,pv,row_number() over (partition by gid order by pv) as pre_total_pv_row_numberfrom test.gid_pvorder bygid,dt;

CUME_DIST函数计算分区中当前行的相对排名:(前面的行数)/(分区中的总行数)
如果有相等值的行(取决于OVER子句中的order by):(前面的行数+相等值行数)/(分区中的总行数)
一般默认升序即可。
selectgid,dt,pv-- (前面的行数)/(分区中的总行数),如果有相等值的行:(前面的行数+相等值行数)/(分区中的总行数),cume_dist() over (partition by gid order by pv) as pre_total_pv_cume_distfrom test.gid_pvorder bygid,dt;
结果数据:

如果想把某个分组内分成比较均匀的几份,可以使用 ntile 函数:(比如想要统计消费金额前 50%的用户的平均消费,可以按照消费金额排序,分成 2 份。)
selectgid,dt,pv,ntile(4) over (partition by gid order by pv) as pre_total_pv_ntilefrom test.gid_pvorder bygid,dt;
参考
https://blog.csdn.net/SunnyYoona/article/details/56488568
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+WindowingAndAnalytics
https://jordenbruce.com/2019/12/09/hql-function-analytic/
订阅


