hive udf 分组取top1_Hive中分组取前N个值的实现-row_number()
背景
假設有一個學生各門課的成績的表單,應用hive取出每科成績前100名的學生成績。
這個就是典型在分組取Top N的需求。
解決思路
對于取出每科成績前100名的學生成績,針對學生成績表,根據學科,成績做order
by排序,然后對排序后的成績,執行自定義函數row_number(),必須帶一個或者多個列參數,如ROW_NUMBER(col1,
....),它的作用是按指定的列進行分組生成行序列。在ROW_NUMBER(a,b)
時,若兩條記錄的a,b列相同,則行序列+1,否則重新計數。
只要返回row_number()返回值小于100的的成績記錄,就可以返回每個單科成績前一百的學生
Sql代碼 ?
create?table?score_table?(
subject?string,
student?string,
score?int
)
partitioned?by?(date?string);
如果要查詢2012年每科成績前100的學生成績,sql如下
Java代碼 ?
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開始自增。
執行row_number函數,返回值如下
科目 成績 學生 row_number
物理 100 張一 1
物理 90 張二 2
物理 80 張三 3
.....
數學 100 李一 1
數學 90 李二 2
數學 80 李三 3
....
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;
同樣,這個函數可以用作去重操作。
可以替代大批量數據的DISTINCT
通過執行如:
select * from(
select type,value,row_number() as rn
from
log_table?distribute by type,value
sort by type,value
)
where rn = 1;
===============注意!============================
但是使用row_number()函數需要注意一點,必須使用sort
by。
測試的時候必須使用order by。
row_number()函數會假設數據有序的基礎上進行的。
總結
以上是生活随笔為你收集整理的hive udf 分组取top1_Hive中分组取前N个值的实现-row_number()的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java互斥锁的实现原理_java-深入
- 下一篇: map insert异常失败_处理dub