轉載:https://blog.csdn.net/knidly/article/details/80265616
簡介
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
輸入結果如下:
neil 411325199308110030 男 pony 41132519950911004x 女 jack 12312423454556561 身份信息不合法! tony 123124234545565 男
說明我們的解析是成功的.
使用
我們在hive中使用python定義的UDF函數要借助transform函數去執行.
transform函數的語法如下:
SELECT TRANSFORM (<columns>) USING 'python <python_script>' AS (<columns>) FROM <table>;
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;
java版本也需要打成jar包,使用add方式添加到hive中
add jar jar_path;
並且要創建函數:
create function fun_name as 'java class name' USING jar 'hdfs_jar_path'; // 上方為官方文檔案例,下面的是我自己寫的,屬於臨時函數,重啟hive后失效 create function fun_name as 'java class name';
查詢:
select fun_name(字段...) from table_name;
我們同樣可以得到如下的結果:
neil 411325199308110030 男 pony 41132519950911004x 女 jack 12312423454556561 身份信息不合法! tony 123124234545565 男