`

hive中分组取前N个值的实现

    博客分类:
  • hive
 
阅读更多

背景

假设有一个学生各门课的成绩的表单,应用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;

 

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

分享到:
评论

相关推荐

    Hive中分组取topN_row_number-rank和dense_rank的使用.pdf

    在这篇文档中,我们将详细学习在Hive中如何进行分组取topN,以及如何使用row_number()、rank()和dense_rank()三种窗口函数进行数据排序和排名。 首先,Hive中的数据表创建和数据插入操作是数据查询和分析的前提。...

    hive 分组取TopN

    hive不直接支持分组取TopN的操作,需要自定义udf函数打成jar包添加到hive运行环境中

    hive udaf 实现按位取与或

    在“hive udaf 实现按位取与或”的场景中,我们主要探讨如何使用UDAF来实现数据的按位逻辑运算,如按位与(AND)和按位或(OR)。 一、Hive UDAF基本概念 UDAF是一种特殊的用户自定义函数,它负责处理一组输入值并...

    部分普通sql查询在hive中的实现方式

    ### 部分普通SQL查询在Hive中的实现方式 Hive是一款基于Hadoop的数据仓库工具,能够对存储在Hadoop文件系统中的数据集进行数据提取、转换、加载(ETL),这是一种可以简化MapReduce编程的工具。由于Hive的设计初衷...

    Apache Hive 中文手册_hive_

    Apache Hive 是基于Hadoop的一个数据仓库工具,用来进行数据提取、转化、加载,这是一种可以存储、查询和分析存储在Hadoop中的大规模数据的机制。hive数据仓库工具能将结构化的数据文件映射为一张数据库表,并提供...

    大数据hive实现原理.zip_hive中怎么更新数据

    桶将数据分组到特定的文件中,而分区则将数据按指定的列值分割到不同的目录下,这样可以更高效地定位和更新数据。 然而,值得注意的是,尽管Hive支持更新数据,但由于其本质的分布式和批处理特性,这类操作相比传统...

    Hive 多行合并和分组limit输出 UDF工具包

    用于多行合并和分组limit输出的udf工具包,已编译配置好,直接调用即可

    Hive中SQL详解

    Hive是一个基于Hadoop构建的数据仓库分析系统,它提供了丰富的SQL查询方式来分析存储在Hadoop分布式文件系统中的数据。 Hive SQL支持绝大多数的语句,如DDL、DML、聚合函数、连接查询、条件查询等。 Hive不适合用于...

    hive所有jar文件

    在Hive中操作HBase,首先需要配置Hive的metastore,指定HBase的Zookeeper节点和表的namespace,然后创建一个外部表,指明表的列族和列,以及对应的HBase表名。一旦设置完成,Hive用户就能像操作普通Hive表一样操作...

    大数据之Hive官方文档简要翻译(中文文档)

    Hive会首先尝试连接列表中的第一个URI,如果失败,则会尝试其他URI。 - `hive.metastore.local`:(从Hive 0.10版本开始废弃)用于指示是否使用本地或远程元存储。如果`hive.metastore.uris`为空,则假设为本地模式...

    Hive函数及语法说明

    这个支持允许用户使用熟悉的 Oracle SQL 语句在 Hive 中执行,提高了工作效率和生产力。 函数说明参考链接 Hive 提供了一个函数说明参考链接,用于查询和了解 Hive 的函数说明。这个链接包括: * SHOW FUNCTIONS;...

    HIVE安装及详解

    HIVE与Hadoop是一种紧密的关系,HIVE可以与Hadoop集成,实现大规模数据的存储和处理。 HIVE与传统数据库对比 HIVE与传统数据库有很多不同之处: * 数据存储:HIVE使用Hadoop分布式文件系统(HDFS)存储数据,而...

    HIVE函数详解大全

    在大数据处理领域,Hive 是一个非常重要的工具,它提供了SQL-like的语言来进行数据查询和分析。本篇文章将详细解析Hive中的各种函数,帮助你更好地理解和应用这些功能。 一、关系运算 关系运算用于比较两个或多个...

    Hive原理与实现

    Hive 是一个构建于 Hadoop 之上的数据仓库工具,它提供了类 SQL 的查询语言(HQL),使得用户可以方便地处理存储在 Hadoop 分布式文件系统(HDFS)中的大规模数据集。Hive 的设计初衷在于降低大数据处理的门槛,让...

    hive2.1.1中orc格式读取报数组越界错误解决方法

    这两个jar包分别是Hive执行引擎和ORC文件格式处理的实现,更新它们可能是为了修复特定版本中的已知问题或提供更好的兼容性。 CDH(Cloudera Distribution Including Apache Hadoop)是Cloudera公司提供的Hadoop发行...

    利用Hive进行复杂用户行为大数据分析及优化案例

    02_Hive表批量加载数据的脚本实现(一) 03_Hive表批量加载数据的脚本实现(二) 04_HIve中的case when、cast及unix_timestamp的使用 05_复杂日志分析-需求分析 06_复杂日志分析-需求字段讲解及过滤 07_复杂日志分析...

    hive实现原理

    ### Hive实现原理详解 #### 一、Hive简介与应用场景 Hive 是一款基于 Hadoop 的数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类 SQL 查询功能,使 MapReduce 编程更加简单,更具通用性。Hive ...

    hive客户端安装_hive客户端安装_hive_

    在大数据处理领域,Hive是一个非常重要的工具,它提供了一个基于Hadoop的数据仓库基础设施,用于数据查询、分析和管理大规模数据集。本教程将详细讲解如何在Linux环境下安装Hive客户端,以便进行数据操作和分析。 ...

    hive级联求和

    在统计学和数据分析中,级联求和是指在一组数据中逐级累加特定字段的值,直到得到一个全局的总和。例如,如果我们有一个销售数据表,包含地区、城市、店铺和每日销售额等信息,级联求和可能需要计算每个地区的总销售...

    Hive使用手册Hive使用手册

    在大数据处理领域,Apache Hive 是一个非常重要的工具,它提供了SQL-like的语言(HQL)用于对存储在Hadoop上的大规模数据进行查询和分析。本手册将深入探讨Hive的概念、数据类型、表的操作以及优化技巧。 1. **Hive...

Global site tag (gtag.js) - Google Analytics