背景

假设有一个学生各门课的成绩的表单,应用hive取出每科成绩前100名的学生成绩。

这个就是典型在分组取Top N的需求。

解决思路

对于取出每科成绩前100名的学生成绩,针对学生成绩表,根据学科,成绩做order by排序,然后对排序后的成绩,执行自定义函数row_number(),必须带一个或者多个列参数,如ROW_NUMBER(col1, ....),它的作用是按指定的列进行分组生成行序列。在ROW_NUMBER(a,b) 时,若两条记录的a,b列相同,则行序列+1,否则重新计数。

只要返回row_number()返回值小于100的的成绩记录,就可以返回每个单科成绩前一百的学生。

解决过程

成绩表结构

create table score_table (subject        string,student       string,score           int
)
partitioned by (date string)

如果要查询2012年每科成绩前100的学生成绩,sql如下

create temporary function row_number as 'com.blue.hive.udf.RowNumber';
select subject,score,student from(select subject,score,student from score where dt='2012'  order by subject,socre desc) order_score
where row_number(subject) <= 100;

com.blue.hive.udf.RowNumber是自定义函数,函数的作用是按指定的列进行分组生成行序列。这里根据每个科目的所有成绩,生成序列,序列值从1开始自增。

假设成绩表的记录如下:

物理  80 张三
数学  100 李一
物理  90  张二
数学  90  李二
物理  100 张一
数学  80  李三.....

经过order by全局排序后,记录如下

物理  100 张一
物理  90  张二
物理  80 张三.....
数学  100 李一
数学  90  李二
数学  80  李三....

接着执行row_number函数,返回值如下

科目  成绩 学生   row_number
物理  100 张一      1
物理  90  张二      2
物理  80  张三      3
.....
数学  100 李一      1
数学  90  李二      2
数学  80  李三      3
....

因为hive是基于MAPREADUCE的,必须保证row_number执行是在reducer中执行。上述的语句保证了成绩表的记录,按照科目和成绩做了全局排序,然后在reducer端执行row_number函数,如果在map端执行了row_number,那么结果将是错误的。

要查看row_number函数在map端还是reducer端执行,可以查看hive的执行计划:

create temporary function row_number as 'com.blue.hive.udf.RowNumber';
explain select subject,score,student from(select subject,score,student from score where dt='2012'  order by subject,socre desc) order_score
where row_number(subject) <= 100;

explain不会执行mapreduce计算,只会显示执行计划。

只要row_number函数在reducer端执行,除了使用order by全局排序配合,也可以使用distribute by + sort by。distribute by可以让相同科目的成绩记录发送到同一个reducer,而sort by可以在reducer端对记录做排序。

而使用order by全局排序,只有一个reducer,未能充分利用资源,相比之下,distribute by + sort by在这里更有性能优势,可以在多个reducer做排序,再做row_number的计算。

sql如下:

create temporary function row_number as 'com.blue.hive.udf.RowNumber';
select subject,score,student from(select subject,score,student from score where dt='2012'  distribute by subject sort by subject asc, socre desc) order_score
where row_number(subject) <= 100;

如果成绩有学院字段college,要找出学院里,单科成绩前一百的学生,解决方法如下:

create temporary function row_number as 'com.blue.hive.udf.RowNumber';
explain select college,subject,score,student from(select college,subject,score,student from score where dt='2012'  order by college asc,subject asc,socre desc) order_score
where row_number(college,subject) <= 100;

如果成绩有学院字段college,要找出学院里,总成绩前一百的学生,解决方法如下:

create temporary function row_number as 'com.blue.hive.udf.RowNumber';
explain select college,totalscore,student from(select college,student,sum(score) as totalscore from score where dt='2012'  group by college,student  order by college asc,totalscore desc) order_score
where row_number(college) <= 100;

row_number的源码

函数row_number(),必须带一个或者多个列参数,如ROW_NUMBER(col1, ....),它的作用是按指定的列进行分组生成行序列。在ROW_NUMBER(a,b) 时,若两条记录的a,b列相同,则行序列+1,否则重新计数。

package com.blue.hive.udf;import org.apache.hadoop.hive.ql.exec.UDF;public class RowNumber extends UDF {private static int MAX_VALUE = 50;private static String comparedColumn[] = new String[MAX_VALUE];private static int rowNum = 1;public int evaluate(Object... args) {String columnValue[] = new String[args.length];for (int i = 0; i < args.length; i++) 『columnValue[i] = args[i].toString();}if (rowNum == 1) {for (int i = 0; i < columnValue.length; i++)comparedColumn[i] = columnValue[i];}for (int i = 0; i < columnValue.length; i++) {if (!comparedColumn[i].equals(columnValue[i])) {for (int j = 0; j < columnValue.length; j++) {comparedColumn[j] = columnValue[j];}rowNum = 1;return rowNum++;}}return rowNum++;}
}

编译后,打包成一个jar包,如/usr/local/hive/udf/blueudf.jar

然后在hive shell下使用,如下:

add jar /usr/local/hive/udf/blueudf.jar;
create temporary function row_number as 'com.blue.hive.udf.RowNumber';
select subject,score,student from(select subject,score,student from score where dt='2012'  order by subject,socre desc) order_score
where row_number(subject) <= 100;

hive 0.12之前可用,0.12之后不可用,只能用窗口函数替代。

参考 http://chiyx.iteye.com/blog/1559460

hive中分组取前N个值的实现相关推荐

  1. Hive中分组取前N个值

    分享两篇文章,结合看更清楚一点. 背景 假设有一个学生各门课的成绩的表单,应用hive取出每科成绩前100名的学生成绩. 这个就是典型在分组取Top N的需求. 解决思路 对于取出每科成绩前100名的 ...

  2. hive udf 分组取top1_Hive中分组取前N个值的实现-row_number()

    背景 假设有一个学生各门课的成绩的表单,应用hive取出每科成绩前100名的学生成绩. 这个就是典型在分组取Top N的需求. 解决思路 对于取出每科成绩前100名的学生成绩,针对学生成绩表,根据学科 ...

  3. map分组后取前10个_hive中分组取前N个值的实现

    背景 假设有一个学生各门课的成绩的表单,应用hive取出每科成绩前100名的学生成绩. 这个就是典型在分组取Top N的需求. 解决思路 对于取出每科成绩前100名的学生成绩,针对学生成绩表,根据学科 ...

  4. hive udf 分组取top1_Hive的经典面试题

    很久没有发文章了,今天发表一下Hive的总结,如果那里有不足的欢迎指正,顺便再提一个问题(数仓建模中:细化程度越高,粒度级就越小,相反,细化程度越低,粒度级就越大,这个说法能打个比方比喻出来吗?) 必 ...

  5. oracle和sql server中,取前10条数据语法的区别

    在sql server中,取数据中前10条语句,我们可以用top 10 这样语句,但是oracle就没有这个函数,接下来介绍它们之间的区别 1.sql server 取前10语句和随机10条的语法 - ...

  6. SQL中如何取前百分之N的记录?

    点击关注公众号,SQL干货及时获取 后台回复:1024,获取海量学习资源 最近帮业务部门梳理业务报表,其中有个需求是就算某指标等待时间最长的前百分之十,其实就是对等待时长进行倒序排序后,取结果集的前百 ...

  7. python学习教程16-数据分组,取前三的值

    一个学校有三个班级,根据成绩取每个班级的前三名: 一个公司有三个销售部门,根据销售业绩取三个部门的销冠... 类型这样的需要有很多种. 一个excel表中,三个sheet(三个班级),把考试成绩的前三 ...

  8. python读取单元格前几个字的值_EXCEL表格中怎么取前一单元格中的前几个字符

    展开全部 截取单元格中前几个字符可以使用LEFT函数.LEFT从文本字符串62616964757a686964616fe4b893e5b19e31333366303138的第一个字符开始返回指定个数的 ...

  9. hive udf 分组取top1_Hive分组取Top K数据

    1.ROW_NUMBER,RANK(),DENSE_RANK() 语法格式:row_number() OVER (partition by COL1 order by COL2 desc ) rank ...

最新文章

  1. JMeter初探三-代理录制
  2. 列索引对SharePoint大列表性能的影响
  3. AI未来说 | 听大牛论自动驾驶领域干货,看无人驾驶小车真实运作
  4. 计算机主机内置的地址码被称为,2016年职称计算机考试WPS_Office单选练习试题1
  5. 关于计算机类课程实验教学的思考
  6. centos7挂载ntfs文件系统_MacOS读写挂载NTFS磁盘,几行代码就行了
  7. shader LOD快速生成具体是种怎样的技术?
  8. 我的缺点,(不断补充中...)
  9. VS2010与.NET4系列 6.ASP.NET,HTML,JavaScript片断支持
  10. 学习数据库的概念,作用
  11. 计算机编程游戏本还是商务本,游戏本和商务本哪个比较适合编程?
  12. 华为MAGICBOOK安装win10专业版,华为MAGICBOOK win10专业版X64下载
  13. IC基础知识(十五)RS触发器、JK触发器、D触发器、T触发器
  14. 当天使爱上吸血鬼,上帝开始哭泣
  15. hadoop是什么?
  16. ⚡性能优化之首屏秒开
  17. 生物信息学linux安装,构建生物信息学环境-1(Win10 Linux子系统的安装)
  18. python实战应用讲解-【numpy科学计算】scikits-statsmodels模块(附python示例代码)
  19. Spark 学习【二】
  20. 怎么查看linux有多少内存插槽,linux 查看内存插槽数、最大容量和频率

热门文章

  1. 分享几个病毒分析检测网址
  2. 远程调用,限制请求超时时间处理
  3. Java哈利波特死亡圣器下_如果编程语言是《哈利波特》中的人物
  4. java 图片组合 分解_切分和组合图片(二)
  5. php 数组元素往后移动,php 二维数组 元素移动
  6. jpa mysql脚本迁移_JPA通过LOAD DATA LOCAL INFILE大批量导入数据到MySQL
  7. 喜用神最正确的算法_各种电磁仿真算法的优缺点和适用范围(FDTD, FEM和MOM等)...
  8. java 合并流_Java Stream 流实现合并操作示例
  9. C语言的typedef用法
  10. SaaS 客户生命周期(逐字稿+PPT)