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;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 无法解决 org.apache.hive:hive-exec:2.3.7 的问题可能有以下几种原因: 1. 版本不兼容:可能当前项目使用的其他依赖库与 org.apache.hive:hive-exec:2.3.7 的版本不兼容。检查一下你使用的所有依赖库,并确保它们与 Hive 的版本兼容。尝试使用与 Hive 相对应的依赖库版本或者升级 Hive 到与你的依赖库版本兼容的版本。 2. 依赖库配置错误:可能在你的项目配置文件(如 pom.xml 或 build.gradle)中没有正确引入 org.apache.hive:hive-exec:2.3.7 依赖库。检查一下你的配置文件,并确保已经正确引入了 Hive 的相关依赖库。如果配置文件中没有该依赖库,尝试添加它到你的配置文件中。 3. 仓库访问问题:如果你使用的依赖库存储在远程仓库中,可能出现了无法访问该仓库的问题。检查一下你的网络连接,并确保可以正常访问依赖库所在的仓库。如果访问受限制,可以尝试使用代理服务器或者更改依赖库的存储位置,例如将其下载到本地并通过本地路径引用。 4. Maven/Gradle 配置问题:如果你使用的是 Maven 或 Gradle 进行构建项目,可能出现了配置问题。检查一下你的构建工具的配置文件,确保已正确设置了仓库地址、依赖库的坐标和版本等信息。如果配置错误,尝试重新配置或参考官方文档以获取正确的配置。 如果以上方法都无法解决 org.apache.hive:hive-exec:2.3.7 的问题,可能需要进一步排查具体错误信息或查找其他人是否遇到了相似的问题。 ### 回答2: 无法解析 org.apache.hive:hive-exec:2.3.7 的原因有多种可能。以下是一些常见的解决方法: 1. 检查是否将正确的 Maven 仓库添加到项目的配置文件中。您可以在项目的pom.xml文件中添加 Hive 依赖项。确保将 Maven 中央仓库添加到配置文件中,以便从中央仓库下载依赖项。 2. 检查网络连接是否正常。如果您的网络连接存在问题,可能无法连接到依赖项所在的 Maven 仓库。确保您的网络连接正常,然后尝试重新构建项目。 3. 检查您正在使用的 Maven 版本是否与项目中指定的依赖项版本不兼容。尝试更新 Maven 版本,并确保使用的 Maven 版本与项目中的依赖项版本兼容。 4. 如果您正在使用的是私有 Maven 仓库,请确保正确配置了仓库的 URL 和凭据信息。有时候,无法解析依赖项是由于未正确配置私有仓库的原因导致的。 5. 检查您本地的 Maven 仓库是否已正确下载和缓存所需依赖项。如果 Maven 仓库中缺少所需的 Hive 依赖项,那么将无法解析该依赖项。您可以尝试删除本地 Maven 仓库中与 Hive 相关的文件,然后重新构建项目以重新下载依赖项。 如果上述方法都无法解决问题,您可能需要进一步检查您的项目配置和环境设置。您还可以搜索相关错误信息和日志,以获得更多关于无法解析依赖项的原因和解决方法的信息。 ### 回答3: 无法解析org.apache.hive:hive-exec:2.3.7的问题可能涉及以下几个方面: 1. 依赖库未添加或版本不正确:检查项目的依赖配置文件中是否添加了org.apache.hive:hive-exec:2.3.7的依赖,如果已添加,请确认版本是否正确。可以尝试通过更新或更换依赖版本来解决问题。 2. 仓库地址或网络连接问题:检查项目的仓库地址是否配置正确,并确认网络连接正常。如果仓库地址无误且网络正常,可能是由于仓库服务器问题导致无法解析依赖库。可以尝试更换其他仓库地址或稍后再次尝试解析。 3. 代理配置问题:如果项目处于代理环境中,需要确保代理配置正确。检查maven的settings.xml文件中的代理配置是否正确,并确认代理服务器的可用性。 4. 本地maven仓库损坏:如果本地maven仓库损坏或缺少相应的依赖库,也可能导致无法解析依赖。可以尝试清理本地maven仓库,并重新下载依赖库。 总之,无法解析org.apache.hive:hive-exec:2.3.7的问题通常是由于依赖配置问题、仓库地址或网络连接问题、代理配置问题、本地maven仓库损坏等原因引起的。根据具体情况逐一排查并解决相应问题,可以解决这个问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值