HIVE中的函数主要可以分为内置函数和自定义UDF函数。
内置函数
内置函数主要分为简单函数、聚合函数、集合函数、特殊函数。
通过show functions查看Hive支持的函数(篇幅问题,只列出了一部分):
hive (default)> show functions;
%
*
+
-
/
<
<=
<=>
<>
=
==
>
>=
abs
and
avg
between
case
ceil
coalesce
concat
cos
count
day
div
exp
explode
if
isnull
length
like
lower
lpad
ltrim
map
max
min
nvl
or
sin
size
split
substr
substring
sum
translate
trim
upper
函数太多我不想一个个教具体使用方法,因为授人以鱼不如授人以渔,而且你也记不住那么多,我想说的是如何学习,这样你随时都可以自行查看使用方法,而不需要死记硬背。
方法一:如果需要查看具体函数信息,使用desc function functionname
hive (default)> desc function coalesce ;
coalesce(a1, a2, ...) - Returns the first non-null argument
hive (default)> desc function lpad ;
lpad(str, len, pad) - Returns str, left-padded with pad to a length of len
hive (default)> desc function ceil ;
ceil(x) - Find the smallest integer not smaller than x
由此我们可以得知 coalesce是返回第一个不为null的值。lpad是左填充,比如lpad(‘abc’,5,’%’) 得到 %%abc。ceil是向上取整。其他函数类似方法去获知它的具体细节。
UDF自定义函数
HIVE支持用户自定义函数,当内置函数无法满足业务需求时,我们就可以自己开发了。
UDF必须是org.apache.hadoop.hive.ql.exec.UDF的子类(即要继承这个类),必须实现evaluate()方法。
因为hive是用java开发的,UDF我们也得java来开发
例如,我要查询id和它的两倍值。java代码如下:
import org.apache.hadoop.hive.ql.exec.UDF;
public class Myfunction extends UDF {
public int evaluate(int num) {
num = num * 2;
return num;
}
public static void main(String[] args) {
}
}
生成对应的jar包并上传到linux上
在hive执行add jar方法 把刚刚传到服务器上的jar包添加到hive上
hive (default)> add jar /usr/local/hive-1.1.0-cdh5.11.1/HadoopLearning.jar;
Added [/usr/local/hive-1.1.0-cdh5.11.1/HadoopLearning.jar] to class path
Added resources: [/usr/local/hive-1.1.0-cdh5.11.1/HadoopLearning.jar]
在hive中创建一个函数,引入的类是我们之前写好的java类UDF.UDFTest
hive (default)> create temporary function doublenum as 'lyl.hive.Myfunction';
OK
Time taken: 0.009 seconds
在hive中使用自定义函数
hive (default)> select id,doublenum(id) from origin;
OK
id _c1
1 2
2 4
3 6
4 8
总结一下步骤:编写java代码–>打包到服务器–>add jar–>create temporary function XXX as ‘XXX’
UDAF自定义函数
UDAF:User- Defined Aggregation Funcation;用户自定义聚合函数,接受多个输入数据行,并产生一个输出数据行;类似SQL中常用的SUM(),AVG(),也是聚合函数。
UDAF有简单与通用两种实现方式:
简单方式:利用抽象类UDAF和UDAFEvaluator,使用Java反射导致性能损失,且有些特性不能使用,如可变长度参数列表。
通用方式:利用接口GenericUDAFResolver2(或抽象类AbstractGenericUDAFResolver)和抽象类GenericUDAFEvaluator,可以使用所有功能,但比较复杂,不直观。
UDAF简单方式的实现
要点
1.继承自”org.apache.hadoop.hive.ql.exec.UDAF”;
2.自定义的内部类要实现接口”org.apache.hadoop.hive.ql.exec.UDAFEvaluator”;
3.要实现iterate()、terminatePartial()、merge()、terminate()四个方法。
* init():类似于构造函数,用于UDAF的初始化
* iterate():每一次对一个新值进行聚集计算时候都会调用该方法,接收传入的参数,并进行内部的轮转,返回boolean。当输入值合法或者正确计算了,就返回true。
* terminatePartial():Hive需要部分聚集结果的时候会调用该方法,其为iterate函数轮转结束后,返回轮转数据。必须要返回一个封装了聚集计算当前状态的对象。无参数。
* merge():接收terminatePartial的返回结果,进行数据merge操作,其返回类型为boolean
* terminate():返回最终的聚集函数结果。
案例
oracle wm_concat(column)函数使我们经常会使用到的,下面我们在HIVE中来实现这个函数。
public class Wm_concat extends UDAF {
public static class myUDAFEval implements UDAFEvaluator {
private PartialResult partial = new PartialResult();
public static class PartialResult{
String result = "";
String delimiter = null;
}
@Override
public void init() {
partial.result ="";
}
public boolean iterate(String value ,String deli){
if(value == null || "null".equalsIgnoreCase(value)){
return true;
}
if(partial.delimiter == null){
partial.delimiter = deli;
}
if(partial.result.length()>0){
partial.result = partial.result.concat(partial.delimiter);//拼接
}
partial.result = partial.result.concat(value);//拼接
return true;
}
public PartialResult terminatePartial(){
return partial;
}
public boolean merge(PartialResult other){
if(other == null ){
return true;
}
if (partial.delimiter == null) {
partial.delimiter = other.result;
partial.result = other.result;
}else{
if (partial.result.length()>0) {
partial.result = partial.result.concat(partial.delimiter);
}
partial.result = partial.result.concat(other.result);
}
return true;
}
public String terminate(){
if(partial==null || partial.result.length()==0){
return null;
}
return partial.result;
}
}
}
接下来和UDF套路一样,打包到服务器–>add jar–>create temporary function XXX as ‘XXX’。
hive (default)> add jar /usr/local/hive-1.1.0-cdh5.11.1/UDAF.jar;
hive (default)> create temporary function wm_concat as 'lyl.hive.Wm_concat';
hive (default)> load data local inpath '/usr/local/hive-1.1.0-cdh5.11.1/udaf.txt' into table test;
hive (default)> select id,concat(name,',') from wm_concat where id is not null group by id;
测试结果:
hive (default)> select * from test;
OK
test.id test.name
1 a
2 b
3 c
1 b
1 c
2 e
3 o
4 p
5 w
Time taken: 0.068 seconds, Fetched: 9 row(s)
hive (default)> select id,wm_concat(name,'---') from test where id is not null group by id;
OK
id _c1
1 a---b---c
2 b---e
3 c---o
4 p
5 w
Time taken: 48.938 seconds, Fetched: 5 row(s)
UDAF通用方式的实现
继承UDAFResolver类,重写 getEvaluator() 方法;
继承GenericUDAFEvaluator类,生成实例给getEvaluator();
在GenericUDAFEvaluator类中,重写init()、iterate()、terminatePartial()、merge()、terminate()方法;
UDTF自定义函数
UDTF(User-Defined Table-Generating Functions) 用来解决 输入一行输出多行(On-to-many maping) 的需求。如常见的explode()函数就是属于UDTF。要实现UDTF,需要继承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF,同时实现三个方法
// 该方法指定输入输出参数:输入的Object Inspectors和输出的Struct。
abstract StructObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException;
// 该方法处理输入记录,然后通过forward()方法返回输出结果。
abstract void process(Object[] record) throws HiveException;
// 该方法用于通知UDTF没有行可以处理了。可以在该方法中清理代码或者附加其他处理输出。
abstract void close() throws HiveException;
BDStar原创文章。发布者:Liuyanling,转载请注明出处:http://bigdata-star.com/archives/1125