Hive UDF的定义

最近在做案例的时候,发现有一个需要解析的字段,Hive中提供的内置函数解析不了.这时候只能自己定义Hive的内置函数了,顺便记录一下。

一、什么是UDF

UDF(User-Defined-Function) 函数其实就是一个简单的函数,执行过程就是在Hive转换成mapreduce程序后,执行java方法,类似于像Mapreduce执行过程中加入一个插件,方便扩展. UDF只能实现一进一出的操作,如果需要实现多进一出,则需要实现UDAF .

Hive可以允许用户编写自己定义的函数UDF,来在查询中使用,下面我们来定义一个UDF

二、UDF定义

1)新建项目

新建JAVA项目 并添加 hive-exec-2.1.1.jar 和hadoop-common-2.7.4.jar依赖

hive-exec-2.1.1.jar 在HIVE安装目录的lib目录下

hadoop-common-2.7.4.jar在hadoop的安装目录下的\share\hadoop\common

根据软件安装的版本不同,拉取不同的jar包

然后将jar包添加到项目依赖中

如果你创建的是Maven项目,则需要把以下依赖添加进项目Pom文件中

<dependency>
    <groupId>org.apache.hive</groupId>
    <artifactId>hive-exec</artifactId>
    <version>2.1.1</version>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>2.7.4</version>
</dependency>

2)重写evaluate方法

新建一个类并继承UDF 并重写evaluate方法

数据类型为17-Jan格式的,是车辆的上牌时间,其中还有好多行数据年份和月份是颠倒的,通过下列代码,我们把这个字段转成车龄

public class DataProcess extends UDF {
    //申明代表月份的map
    private static Map<String,String> map = new HashMap<>();
    static {
        //在静态代码块中给map put元素
        map.put("Jan","01");
        map.put("Feb","02");
        map.put("Mar","03");
        map.put("Apr","04");
        map.put("May","05");
        map.put("Jun","06");
        map.put("Jul","07");
        map.put("Aug","08");
        map.put("Sep","09");
        map.put("Oct","10");
        map.put("Nov","11");
        map.put("Dec","12");
    }


    public Text evaluate(Text text){
        //数据类型 17-Jan
        //切分数据  将数据切分为年份  和 月份
        String[] split = text.toString().split("-");
        //获取到需要的月份类型
        String month=null;
        String s=null;
//数据中有一些不规范的日期,年份和月份反过来了 这里我们判断一下,把他纠正
        if (split[1].length()==3){
            month = map.get(split[1]);
            if (split[0].length() < 2) {

                s = "200" + split[0] + "-" + month;
            } else {
                s = "20" + split[0] + "-" + month;
            }
        }else{
            month = map.get(split[0]);
            //根据月份位数的不同  来拼接成日期
            if (split[1].length() < 2) {

                s = "200" + split[1] + "-" + month;
            } else {
                s = "20" + split[1] + "-" + month;
            }
        }
        if (month==null|| "".equals(month)){
            return new Text("");
        }

        //将日期字符串转换为date
        DateFormat df = new SimpleDateFormat("yyyy-MM");
        Date parse = null;
        try {
            parse = df.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //获取到当前时间 毫秒
        long l = System.currentTimeMillis();
        //计算时间差
        long l1 = l - parse.getTime();
        Long lin = 1000 * 60 * 60 * 24 * 365L;
        //使用DecimalFormat 来保留两位小数
        DecimalFormat decimalFormat = new DecimalFormat("0.00");//格式化小数
        //获取到年份返回
        String num = decimalFormat.format((float) l1 / lin);//返回的是String类型

        return   new Text(num)  ;

    }

}

3)上传并使用

编写完成后将,代码打包(带依赖)上传到集群中.
上传jar
因为我是用SparkSQL操作的Hive中的数据,所以我需要重启Spark SQL 命令行,把Jar指定进去

spark-sql  --jars /root/used_car/udf.jar   --master spark://hbase01:7077

将自定义的方法添加进内置函数中

CREATE TEMPORARY FUNCTION huatec_date AS 'com.huatec.udf.DataProcess';

创建方法

huatec_date为内置函数的名称

com.huatec.udf.DataProcess 为jar包中方法的全类名

temporary表示为临时方法,当会话结束后失效

这时候就可以将上牌时间解析为车龄了

一起来试试吧!!!~~~~~

SELECT
 card_time,
 huatec_date (card_time) AS car_age
FROM
 car_used_info
LIMIT 10;

查询
到这里一个Hive UDF 就定义好了 ~~~~~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值