hive分组排序 取top N

pig可以轻松获取TOP n。书上有例子

hive中比较麻烦,没有直接实现的函数,可以写udf实现。还有个比较简单的实现方法:
用row_number,生成排名序列号。然后外部分组后按这个序列号多虑,样例代码如下
select a.*
from(   
    select 品牌,渠道,档期,count/sum/其它() as num row_number() over (partition by 品牌,渠道 order by num desc ) rank
    from table_name
    where 品牌,渠道 限制条件
    group by 品牌,渠道,档期
    )a
where a.rank<=10

其实 排序有三个函数
(1)row_number:排序后,顺序下来,相同项按先后顺序排序,1,2,3,4,5
(2)rank:排序后,遇到数据相同项时序号一致,后面并留空一位,比如,1,2,2,4,4,6

dense_rank:在遇到数据相同项时,序号一致,不留空位,如 1,2,2,3,3,4,4,5

具体用例可以参见:http://www.cnblogs.com/dycg/p/4260283.html

我自己设计的代码

##统计国内,各省份的城市排名
select b.*
from
(select country,
    province,
    city,
    cnt,
    row_number() over (partition by country,province order by cnt desc) rank
from 
    (select country,
            province,
            city,
            count(1) as cnt
    from tb_pmp_region_report_hive_mapping
    where country = '中国'
    group by country,province,city
    ) a
)b
where b.rank<=3

表a统计出基本数据,从a中加排名项。然后,按排名项过滤。内部group后,外部不需要group by

需要注意的是,加排名项时,不应该使用group。
如果有group,那么row_number中的order by项必须是group内的字段,否则报错,如下段代码报错
select b.*
from
(select country,
    province,
    city,
    cnt,
    row_number() over (partition by country,province order by cnt desc) rank
from 
    (select country,
            province,
            city,
            count(1) as cnt
    from tb_pmp_region_report_hive_mapping
    where country = '中国'
    group by country,province,city
    ) a
    group by country,province,city
)b
where b.rank<=3

执行报错:
FAILED: SemanticException Failed to breakup Windowing invocations into Groups. At least 1 group must only depend on input columns. Also check for circular dependencies.
Underlying error: org.apache.hadoop.hive.ql.parse.SemanticException: Line 7:62 Expression not in GROUP BY key ‘cnt’
hive>

posted on 2016-01-15 18:43  代码王子  阅读(4010)  评论(0编辑  收藏  举报

导航