本文部分参考自:https://blog.csdn.net/qq_23897391/article/details/100688796
自己的话:千里之行,始于足下。
每天都要保持前进,我势必要有强劲的实力,再跟明天的自己问好。
开窗函数的固定写法:
over(partition by 列名1,列名2 …… order by 列名3,列名4 …… [desc])
新建test.txt文件,输入如下的三列数据,以空格分隔。第一列是月份,第二列代表商铺名称,第三列代表该商铺该月营业额(万元)。
[root@hadoop ~]# vim test.txt
2019-01 a 4
2019-01 b 3
2019-01 c 3
2019-01 d 2
2019-01 e 1
2019-02 a 1
2019-02 b 2
2019-02 c 3
2019-02 d 3
2019-02 e 4
在hive中新建表temp_test10,将test文件中的数据插入,查看数据。
hive >CREATE TABLE temp_test10 (
>month STRING comment '月份',
>shop STRING comment '商铺名称',
>money STRING comment '营业额(万元)')
>row format delimited
>fields terminated BY ' ';
hive >load data local inpath '/root/test.txt' into table temp_test10;
hive >select * from temp_test10;
temp_test10.month temp_test10.shop temp_test10.money
2019-01 a 4
2019-01 b 3
2019-01 c 3
2019-01 d 2
2019-01 e 1
2019-02 a 1
2019-02 b 2
2019-02 c 3
2019-02 d 3
2019-02 e 4
row_number()会生成数据项在分组中的排名,排名即便相等也不会有并列排名,相同排名随机排序。
首先按照月份进行分组,然后每个组内按照营业额从大到小排序,为组内每一行数据得到一个唯一序号。
hive >SELECT month,shop,MONEY,row_number()
>OVER (PARTITION BY month ORDER BY MONEY DESC --按照月份进行分组,然后每个组内按照营业额从大到小排序)
>AS rk --生成的排序序号
>FROM temp_test10
结果:
month shop money rk
2019-01 a 4 1
2019-01 c 3 2
2019-01 b 3 3
2019-01 d 2 4
2019-01 e 1 5
2019-02 e 4 1
2019-02 d 3 2
2019-02 c 3 3
2019-02 b 2 4
2019-02 a 1 5
取出1月和2月每个月营业额排名前3的店铺及营业额。
使用子查询取出rk<=3的数据即可
hive >SELECT *
>FROM (SELECT month,shop,MONEY,row_number()
>OVER (PARTITION BY month ORDER BY MONEY DESC --按照月份进行分组,然后每个组内按照营业额从大到小排序)
>AS rkFROM temp_test10) a
>WHERE rk <= 3;
结果:
a.month a.shop a.money a.rk
2019-01 a 4 1
2019-01 c 3 2
2019-01 b 3 3
2019-02 e 4 1
2019-02 d 3 2
2019-02 c 3 3
如果只有一个分组,那么可以省略partition by,比如只取出1月营业额排名前3的店铺及营业额。
hive >SELECT *
>FROM (SELECT month,shop,MONEY,row_number()
>OVER (ORDER BY MONEY DESC --按照营业额从大到小排序)
>AS rkFROM temp_test10WHERE month = '2019-01') a
>WHERE rk <= 3;
结果:
a.month a.shop a.money a.rk
2019-01 a 4 1
2019-01 c 3 2
2019-01 b 3 3
row_number()配合rand()函数即可实现每个分组内取出n个随机值的需求。
每个月随机抽取两家店铺:
hive >SELECT *
>FROM (SELECT month,shop,MONEY,row_number()
>OVER (PARTITION BY month ORDER BY rand(1) --可以使用任意数作为种子进行随机排序,也可以不填,直接使用rand())
>AS rk FROM temp_test10) a
>WHERE rk <= 2; --限制rk来取出n个随机值
结果:
a.month a.shop a.money a.rk
2019-01 c 3 1
2019-01 d 2 2
2019-02 a 1 1
2019-02 e 4 2
rank()可以生成数据项在分组中的排名,排名相等时会产生并列排名,然后会在名次中留下空位。应用场景不多,很少需要使用,了解即可。
首先按照月份进行分组,然后每个组内按照营业额从大到小排序,生成排名,并列排名后留下空位。
hive >SELECT month,shop,MONEY,rank()
>OVER (PARTITION BY month ORDER BY MONEY DESC --按照月份进行分组,然后每个组内按照营业额从大到小排序)
>AS rk --生成的排序序号
>FROM temp_test10;
结果:
month shop money rk
2019-01 a 4 1
2019-01 c 3 2
2019-01 b 3 2
2019-01 d 2 4
2019-01 e 1 5
2019-02 e 4 1
2019-02 d 3 2
2019-02 c 3 2
2019-02 b 2 4
2019-02 a 1 5
dense_rank()可以生成数据项在分组中的排名,排名相等时会产生并列排名,但不会在名次中留下空位。应用场景也不多,很少需要使用,了解即可
首先按照月份进行分组,然后每个组内按照营业额从大到小排序,生成排名,并列排名后不要留下空位。
hive >SELECT month,shop,MONEY,dense_rank()
>OVER (PARTITION BY month ORDER BY MONEY DESC --按照月份进行分组,然后每个组内按照营业额从大到小排序)
>AS rk --生成的排序序号
>FROM temp_test10;
结果:
month shop money rk
2019-01 a 4 1
2019-01 c 3 2
2019-01 b 3 2
2019-01 d 2 3
2019-01 e 1 4
2019-02 e 4 1
2019-02 d 3 2
2019-02 c 3 2
2019-02 b 2 3
2019-02 a 1 4
最后,再拿出一个我自己的举例:
求每个人前两高的分数
vi score.txt
zhangsan,1,90,2
zhangsan,2,95,1
zhangsan,3,68,3
lisi,1,88,3
lisi,2,95,2
lisi,3,98,1
hive >create table t_score(name string,kcid string,score int)
>row format delimited
>fields terminated by ',';
hive>load data local inpath '/home/score.txt' into table t_score;
hive> select *,row_number() over(partition by name order by score desc) rank from t_score;
hive >select name,kcid,score
>from(select *,row_number() over(partition by name order by score desc) as rank from t_score) tmp
>where rank<3;
求出每个用户评分最高的3部电影
建表并加载数据
hive >create table t_rate_topn_uid
>as
>select uid,movie,rate,ts
>from(select *,row_number() over(partition by uid order by rate desc) as rank from t_rate) tmp
>where rank<11;
查询
hive> select * from t_rate_topn_uid where uid=1;
这样,开窗函数中的组内排序就介绍完了,希望对大家有所帮助,可别忘了点赞。