首页 > Web开发 > 详细

HIVE的自定义udf函数-extends GenericUDF--链接自:https://blog.csdn.net/eyeofeagle/article/details/83688719

时间:2020-03-16 20:58:09      阅读:111      评论:0      收藏:0      [点我收藏+]

------------恢复内容开始------------

在大数据项目,使用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

自定义udf

 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

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!