Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1034848
  • 博文数量: 164
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1336
  • 用 户 组: 普通用户
  • 注册时间: 2016-03-11 14:13
个人简介

狂甩酷拽吊炸天

文章分类

全部博文(164)

文章存档

2023年(1)

2022年(3)

2021年(4)

2020年(17)

2019年(37)

2018年(17)

2017年(35)

2016年(50)

分类: 大数据

2019-04-10 19:45:00

简介
Hive为我们提供了众多的内置函数,但是在实际的运用过程中仍然不能满足我们所有的需求.hive是用java开发的,本身提供了使用java去开发UDF的方式.而这里我们采用python的方式去实现UDF函数.


DEMO实现
我们这里用python自定义函数,去实现一个方法,利用身份证号去判断性别(18位身份证的倒数第二位偶数为女,奇数为男.15位身份证的倒数第一位偶数为女,奇数为男.).其实这个需求可以使用hive自带的function去进行解决.我们接下来使用2种方式去实现这个需求.


数据准备
我们在hive上创建一个external表(名字person表),执行如下代码:


create external table person(
name string,
idcard string)
ROW FORMAT DELIMITED 
FIELDS TERMINATED BY '\t'
STORED as TEXTFILE;

该表两个字段,一个为name,另一个为idcard 
数据格式如下:


neil    411326199402110030
pony    41132519950911004x
jcak    12312423454556561
tony    412345671234908

field分隔符使用\t 
我们将数据放入hive的warehouse中:


hdfs dfs -put person.txt /user/hive/warehouse/test_neil.db/person

执行select,我们发现数据已经进入到hive了.


使用Hive Function去实现
我们可以执行一下的hql去实现


select idcard,
case when length(idcard) = 18 then
             case when substring(idcard,-2,1) % 2 = 1 then '男' 
             when substring(idcard,-2,1) % 2 = 0 then '女' 
             else 'unknown' end 
     when length(idcard) = 15 then 
            case when substring(idcard,-1,1) % 2 = 1 then '男'
            when substring(idcard,-1,1) % 2 = 0 then '女'
            else 'unknown' end
     else '不合法' end 
from person;

得到的结果如下(beeline下):


+---------------------+------+--+
|       idcard        | _c1  |
+---------------------+------+--+
| 12312423454556561   | 不合法  |
| 123124234545565     | 男    |
| 411325199308110030  | 男    |
| 41132519950911004x  | 女    |

UDF编写
如下是我们的udf代码:


# -*- coding: utf-8 -*-
import sys


for line in sys.stdin:
    detail = line.strip().split("\t")
    if len(detail) != 2:
        continue
    else:
        name = detail[0]
        idcard = detail[1]
        if len(idcard) == 15:
            if int(idcard[-1]) % 2 == 0:
                print("\t".join([name,idcard,"女"]))
            else:
                print("\t".join([name,idcard,"男"]))
        elif len(idcard) == 18:
            if int(idcard[-2]) % 2 == 0:
                print("\t".join([name,idcard,"女"]))
            else:
                print("\t".join([name,idcard,"男"]))
        else:
            print("\t".join([name,idcard,"身份信息不合法!"]))

这里我们使用python的重定向,将hive控制台的输出进行split,split默认使用的为\t.然后根据split后的idcard的倒数第二位进行判断这个人的性别.


 测试
我们在hive中去执行查询时,报错的提示不是很详细.我们可以使用cat指令去测试python脚本的执行效果. 
我们在终端中执行如下指令:


cat person.txt|python person.py
1
输入结果如下:


neil    411325199308110030  男
pony    41132519950911004x  女
jack    12312423454556561   身份信息不合法!
tony    123124234545565 男

说明我们的解析是成功的.


使用
我们在hive中使用python定义的UDF函数要借助transform函数去执行. 
transform函数的语法如下:


SELECT TRANSFORM ()
USING 'python '
AS ()
FROM ;

transfrom和as的columns的个数不必一致. 
我们首先需要将我们的person.py加载入


我们在hive中去执行如下代码:


add file /xxx/person.py

xxx为本地文件的路径. 
然后使用transform函数执行:


select transform(name,idcard) USING 'python person.py'  AS (name,idcard,gender) from person;
1
我们同样可以得到如下的结果:

neil    411325199308110030  男
pony    41132519950911004x  女
jack    12312423454556561   身份信息不合法!
tony    123124234545565 男

阅读(5602) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~