文章目录
一、UDF 介绍
UDF(User-Defined Functions)即是用户自定义的hive函数。当 Hive 自带的函数并不能完全满足业务的需求,这时可以根据具体需求自定义函数。UDF 函数可以直接应用于 select 语句,对查询结构做格式化处理后,再输出内容。
Hive 自定义函数包括三种:
- UDF: one to one ,进来一个出去一个,row mapping, 如:upper、substr函数;
- UDAF(A:aggregation): many to one,进来多个出去一个,row mapping,如sum/min;
- UDTF(T:table-generating):one to mang,进来一个出去多行,如 lateral view 与 explode 。
注解使用:
@Describtion 注解是可选的,用于对函数进行说明,其中的 FUNC 字符串表示函数名,当使用 DESCRIBE FUNCTION 命令时,替换成函数名。@Describtion包含三个属性:
- name:用于指定 Hive 中的函数名。
- value:用于描述函数的参数。
- extended:额外的说明,如,给出示例,当使用 DESCRIBE FUNCTION EXTENDED name 的时候打印。
二、UDF
开发自定义 UDF 函数有两种方式:
- 如果函数读和返回都是基础数据类型,即 Hadoop 和 Hive 的基本类型,如,Text、IntWritable、LongWritable、DoubleWritable 等,那么继承 org.apache.hadoop.hive.ql.exec.UDF ;
- 如果用来操作内嵌数据结构,如 Map,List 和 Set,则继承 org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
2.1、简单 UDF
用简单 UDF API 来构建一个 UDF 只涉及到编写一个类继承实现一个方法(evaluate),下面的例子来自 《Hive 编程指南》,将表中的生日字段转换为星座。
@UDFType
@Description(
name = "zodiac",
value = "_FUNC_ (date) - " +
" from the input date string " +
" or separate month and day arguments, \n" +
" returns the sign of the Zodiac.",
extended = "Example :\n" +
"> SELECT _FUNC_ (date_string) FROM src;\n" +
"> SELECT _FUNC_ (month, day) FROM src;")
public class UDFZodiacSign extends UDF {
private static final String ERROR_DATE_OF_MONTH = "invalid date of specify month";
private static final String ERROR_MONTH_ARGS = "invalid argument of month";
private static final String ERROR_DATE_STRING = "invalid date format";
public String evaluate(Date bday) {
return this.evaluate(bday.getMonth() + 1, bday.getDate());
}
public String evaluate(String dateString) {
DateTime dateTime;
try {
dateTime = new DateTime(dateString);
} catch (Exception e) {
return ERROR_DATE_STRING;
}
return this.evaluate(dateTime.getMonthOfYear(), dateTime.getDayOfMonth());
}
public String evaluate(Integer month, Integer day) {
switch (month) {
//判断是几月
case 1:
//判断是当前月的哪一段时间;然后就可以得到星座了;下面代码都一样的
if (day > 0 && day < 20) {
return "魔蝎座";
} else if (day < 32) {
return "水瓶座";
} else {
return ERROR_DATE_OF_MONTH;
}
case 2:
if (day > 0 && day < 19) {
return "水瓶座";
} else if (day < 29) {
return "双鱼座";
} else {
return ERROR_DATE_OF_MONTH;
}
case 3:
if (day > 0 && day < 21) {
return "双鱼座";
} else if (day < 32) {
return "白羊座";
} else {
return ERROR_DATE_OF_MONTH;
}
case 4:
if (day > 0 && day < 20) {
return "白羊座";
} else if (day < 31) {
return "金牛座";
} else {
return ERROR_DATE_OF_MONTH;
}
case 5:
if (day > 0 && day < 21) {
return "金牛座";
} else if (day < 32) {
return "双子座";
} else {
return ERROR_DATE_OF_MONTH;
}
case 6:
if (day > 0 && day < 22) {
return "双子座";
} else if (day < 31) {
return "巨蟹座";
} else {
return ERROR_DATE_OF_MONTH;
}
case 7:
if (day > 0 && day < 23) {
return "巨蟹座";
} else if (day < 32) {
return "狮子座";
} else {
return ERROR_DATE_OF_MONTH;
}
case 8:
if (day > 0 && day < 23) {
return "狮子座";
} else if (day < 32) {
return "处女座";
} else {
return ERROR_DATE_OF_MONTH;
}
case 9:
if (day > 0 && day < 23) {
return "处女座";
} else if (day < 31) {
return "天平座";
} else {
return ERROR_DATE_OF_MONTH;
}
case 10:
if (day > 0 && day < 24) {
return "天平座";
} else if (day < 32) {
return "天蝎座";
} else {
return ERROR_DATE_OF_MONTH;
}
case 11:
if (day > 0 && day < 23) {
return "天蝎座";
} else if (day < 31) {
return "射手座";
} else {
return ERROR_DATE_OF_MONTH;
}
case 12:
if (day > 0 && day < 22) {
return "射手座";
} else if (day < 32) {
return "摩羯座";
} else {
return ERROR_DATE_OF_MONTH;
}
default:
return ERROR_MONTH_ARGS;
}
}
}
测试一下:
public