阿里云大数据利器Maxcompute学习之--窗口函数实现分组TopN

看到很多用户经常会问如何对分组内进行排序。
官方文档:https://help.aliyun.com/document_detail/34994.html?spm=5176.doc27891.6.611.Q1bk3j
例如需求:

  1. odps 里面能否做排名操作,比如一个表里面有 用户ID 和 金额 两个字段,用金额大小排序的话,我如何计算用户的排名(金额最大的是 第一名 ,以此类推)
  2. 计算每个金融产品的最大投资者,或者前几名

类似这一类的需求,我们总结为实现分组内的排序,取TopN,那么在hive中有两个个函数可以分开实现
first_value: 取分组内排序后,截止到当前行,第一个值,
row_number():实现组内排序,并对组内行进行标记行号。
那在odps中没有first_value这个函数,但是同样可以实现top1的需求。下面用一个大家最爱的公司员工表来举例实现

员工表:

empnoenamejobmgrhiredatesalcommdeptno
7839KINGPRESIDENTNULL1981-11-17 00:00:005000.0NULL10
7566JONESMANAGER78391981-04-02 00:00:002975.0NULL20
7698BLAKEMANAGER78391981-05-01 00:00:002850.0NULL30
7788SCOTTANALYST75661987-07-13 01:00:003000.0NULL20
7782CLARKMANAGER78391981-06-09 00:00:002450.0NULL10
7369SMITHCLERK79021980-12-17 00:00:00800.0NULL20
7902FORDANALYST75661981-12-03 00:00:003000.0NULL20
7876ADAMSCLERK77881987-07-13 01:00:001100.0NULL20
7900JAMESCLERK76981981-12-03 00:00:00950.0NULL30
7934MILLERCLERK77821982-01-23 00:00:001300.0NULL10
7499ALLENSALESMAN76981981-02-20 00:00:001600.0300.030
7654MARTINSALESMAN76981981-09-28 00:00:001250.01400.030
7844TURNERSALESMAN76981981-09-08 00:00:001500.00.030
7521WARDSALESMAN76981981-02-22 00:00:001250.0500.030

使用row_number()对相同 job 的薪水sal 进行

排序,取组内最大,等不及了,直接上sql

select * from (
    select job,sal,
     row_number() over(partition by job order by sal desc) as rn  from emp
 ) a where rn=1;
//partition by 跟分组字段
//order by 跟排序字段+升降关键字 默认升序排列。

结果:

jobsalrn
ANALYST3000.01
CLERK1300.01
MANAGER2975.01
PRESIDENT5000.01
SALESMAN1600.01

同理如果想实现topN,那把rn=1改成rn

select * from (

select job,ename,sal,
 row_number() over(partition by job order by sal desc) as rn  from emp

) a where rn<3;

结果:

jobenamesalrn
ANALYSTSCOTT3000.01
ANALYSTFORD3000.02
CLERKMILLER1300.01
CLERKADAMS1100.02
MANAGERJONES2975.01
MANAGERBLAKE2850.02
PRESIDENTKING5000.01
SALESMANALLEN1600.01
SALESMANTURNER1500.02

那这是一个简单的例子。
对于类似需求可以用这个方法来实现TopN的计算。
注意:这种方法对于数量级不是很大的或者分组比较均匀的大数据量实用,
如果分组键值不均匀,导致单个或者几个键值比较大,那会有数据倾斜的问题。此时我们可以从sql上优化写法,例如可以排查哪几个键值比较大单独拉出来一个任务执行。

有对大数据技术感兴趣的,可以加笔者的微信 wx4085116.目前笔者已经从阿里离职,博客不代表阿里立场。笔者开了一个大数据培训班。有兴趣的加我。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值