------------恢复内容开始------------
在大数据项目,使用hive时会遇到某些场景需要自定义函数,如日期处理:
那么如何在hive中要自定udf函数呢? 只要定义一个类Myudf 继承org.apache.hadoop.hive.ql.udf.generic.GenericUDF,然后打成Jar包, 发送到hive所在机器或hdfs, 登录hive, 使用命令创建函数:
create function myfun1 as "包名.Myudf" using jar "hdfs:/jars/myudf_jar"; |
GenericUDF 类的文档描述为:
它可以接受复杂类型的参数,并返回复杂类型
它可以接受可变长度的参数
它可以接受无限数量的函数签名——例如,很容易编写一个接受数组等等(任意嵌套级别)的GenericUDF
它可以使用延迟对象进行短路评估
它有三个抽象方法必须实现(getDisplayString, initialize, evalute ),具体使用如下:
初始化判断: initialize方法
类型判断 | ois[0].getCategory() != ObjectInspector.Category.PRIMITIVE | (((PrimitiveObjectInspector) ois[0])).getPrimitiveCategory() != PrimitiveObjectInspector.PrimitiveCategory.INT、STRING、LONG |
参数–(映射)–转换器 | 准备转换器数组: converters = new ObjectInspectorConverters.Converter[4] |
ObjectInspectorConverters.getConverter(ois[0], PrimitiveObjectInspectorFactory.javaIntObjectInspector、 javaLongObjectInspector、 javaStringObjectInspector ); |
在hive中被调用的方法: evaluate , 解析参数生成新的数据
解析参数 | 返回结果 |
int offset = (Integer)converters[0].convert(arguments[0].get()) | return XXX |
1 类FormatByDayUDF extends GenericUDF { // initialize, evalute 2 3 //属性 4 ObjectInspectorConverters.Converter[] converters = new ObjectInspectorConverters.Converter[4] 5 6 //方法1 7 ObjectInspector initialize(ObjectInspector[] ois){ 8 //判断: 参数类型 9 ois[0].getCategory() != ObjectInspector.Category.PRIMITIVE 10 (((PrimitiveObjectInspector) ois[0])).getPrimitiveCategory() != PrimitiveObjectInspector.PrimitiveCategory.INT、STRING、LONG) //类型 11 12 //参数 <--->参数转换器 13 converters[0] = ObjectInspectorConverters.getConverter(ois[0], PrimitiveObjectInspectorFactory.javaIntObjectInspector、 javaLongObjectInspector、 javaStringObjectInspector ); 14 } 15 16 //方法2 17 Object evaluate(DeferredObject[] arguments){ 18 19 //一个参数: formatDay(-1) 20 int offset = (Integer)converters[0].convert(arguments[0].get()) ; 21 Calendar cal = Calendar.getInstance(); 22 cal.setTime( new Date() ) ; 23 cal.add(Calendar.DAY_OF_MONTH , offset);//计算日期: 前n天, 后n天 [long] 24 return new SimpleDateFormat( "yyyyMMdd" ) .format(cal.getTime()) ;//日期格式化:【“2018 09 01”】 25 26 //两个参数: formatDay(-1 , ‘yyyy/MM/dd‘) 27 //三个参数: formatDay(154xxxx ,-1 , ‘yyyy/MM/dd‘) 28 //四个参数: formatDay(‘2018/12/12‘ , ‘yyyy/MM/dd‘, -1 , ‘yyyy/MM/dd‘) 29 } 30 }
1 String formatDay(Date date , int offset , String fmt){ //前n天, 后n天 2 Calendar cal = Calendar.getInstance(); 3 cal.setTime(date) ; 4 5 //在day的成分上进行累加累减 6 cal.add(Calendar.DAY_OF_MONTH , offset); 7 return new SimpleDateFormat(fmt).format(cal.getTime()) ; 8 } 9 10 11 String formatWeek(Date date , int offset , String fmt){ //上周几, 下周几 12 Calendar cal = Calendar.getInstance(); 13 cal.setTime(date) ; 14 //取出指定date位于当前周的第几天 15 int n = cal.get(Calendar.DAY_OF_WEEK) ; 16 17 //在day的成分上进行累加累减 18 cal.add(Calendar.DAY_OF_MONTH , -(n - 1)); 19 cal.add(Calendar.DAY_OF_MONTH , offset * 7); 20 } 21 22 String formatMonth(Date date , int offset , String fmt){ //上n月, 下n月 23 Calendar cal = Calendar.getInstance(); 24 cal.setTime(date) ; 25 26 cal.add(Calendar.MONTH , offset); 27 return new SimpleDateFormat(fmt) .format(cal.getTime()) ; 28 }
活跃统计:日活,周活,月活 select count( distinct concat( appid, deviceid, appplatform, brand, devicestyle, ostype, appversion ) ) from appstartuplogs where appid is not null and deviceid is not null and concat(ym,day)=formatbyday(-1,"yyyyMMdd"); #指定日活统计: # and concat(ym,day)=formatbyweek(-1,"yyyyMMdd"); #指定周活统计: # and concat(ym,day)=formatbymonth(-1,"yyyyMMdd"); #指定月活统计
HIVE的自定义udf函数-extends GenericUDF--链接自:https://blog.csdn.net/eyeofeagle/article/details/83688719
原文:https://www.cnblogs.com/hyll/p/12506414.html