hive 分组取top n的写法

注:技术交流可以加我VX:k-loop,昵称:默读者。

创建测试表

create table tmp_ma(
class  string comment'品类',
brand  string comment'品牌',
sales  int comment'销量'
)

插入测试数据

insert into tmp_ma(class,brand,sales) values('手机','小米',10);
insert into tmp_ma(class,brand,sales) values('手机','华为',9);
insert into tmp_ma(class,brand,sales) values('手机','荣耀',6);
insert into tmp_ma(class,brand,sales) values('手机','一加',13);
insert into tmp_ma(class,brand,sales) values('手机','诺基亚',2);
insert into tmp_ma(class,brand,sales) values('手机','锤子',15);
insert into tmp_ma(class,brand,sales) values('电脑','小米',3);
insert into tmp_ma(class,brand,sales) values('电脑','华为',3);
insert into tmp_ma(class,brand,sales) values('电脑','联想',20);
insert into tmp_ma(class,brand,sales) values('电脑','戴尔',15);
insert into tmp_ma(class,brand,sales) values('电脑','华硕',15);
insert into tmp_ma(class,brand,sales) values('电脑','三星',10);

需求,按照品类分组,取出销量前3的品牌来。

分析,我们先手动的排名,在手机这个品类里,每个品牌的销量都不同,没有并列的情况,这是我们最想看到的情况,但是在

电脑这个品类里,戴尔和华硕并列排名第2,如果只取每个品牌的销量的前3的3条记录,那么电脑里,只取,联想,戴尔,华硕就够了。

select
k.*
from (
select 
ROW_NUMBER() OVER(PARTITION BY t.class ORDER BY t.sales desc) MM
,t.*
from tmp_ma t
) k
where k.mm<=3;

另一种写法:

select
k.*
from (
select 
rank()  OVER(PARTITION BY t.class ORDER BY t.sales desc) MM
,t.*
from tmp_ma t
) k
where k.mm<=3;

如果,并列的联想和华硕算第2名,还需向下取出第3名来。

select
k.*
from (
select 
DENSE_RANK()  OVER(PARTITION BY t.class ORDER BY t.sales desc) MM
,t.*
from tmp_ma t
) k
where k.mm<=3;

总结:ROW_NUMBER(),RANK(),DENSE_RANK() 这3种排名的差异

1,ROW_NUMBER()

如上图,戴尔和华硕的销量虽然都是15,但是排名,戴尔是第2,华硕是第3,这个方法,可以避免取重复数据,例如我只想从排名第2里取出一条数据就行,那么这个方法只会取到戴尔。

有的时候,我们只会取最新的一条记录,那么建议使用这个方法,避免了取重复数据。

2,RANK()

这个方法,会把戴尔和华硕排名都为第2,因为有两个并列第2,那么就不会出现排名是3的记录,如果有3个排名第2的,那么就不会出现排名是3,4的记录。

3,DENSE_RANK()

这个方法,会把戴尔和华硕排名都为第2,三星排名是第3。

简单记忆法:

ROW_NUMBER() 无并列无跳跃排名

RANK() 有并列有跳跃排名

DENSE_RANK() 有并列无跳跃排名

over()里头的分组以及排序的执行晚于 where 、group by、  order by 的执行。

ROW_NUMBER()函数作用就是将select查询到的数据进行排序,每一条数据加一个序号,一般多用于分页查询。

RANK()函数,顾名思义排名函数,可以对某一个字段进行排名,这里为什么和ROW_NUMBER()不一样那,ROW_NUMBER()是排序,当存在相同销量时,ROW_NUMBER()会依次进行排序,他们序号不相同,而Rank()则不一样出现相同的,他们的排名是一样的。

DENSE_RANK()函数也是排名函数,和RANK()功能相似,也是对字段进行排名,那它和RANK()到底有什么不同那?DENSE_RANK()排名是连续的,RANK()是跳跃的排名,所以一般情况下用的排名函数就是RANK()。

实际编程中,根据需要,选择合适的方法。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值