Hive之函数

目录

一、系统内置函数

二、常用内置函数

1.空字段赋值

2.case语句

3.行转列

4.列转行

5.窗口函数

RANK函数

6.自定义函数以及举例


一、系统内置函数

日期类
unix_timestamp:返回指定时间的时间戳
select unix_timestamp('2021-12-23 12-51-25','yyyy-MM-dd HH-mm-ss');
from_unixtime:将时间戳转化为具体时间 select from_unixtime(1640263885);
current_date:当前日期 select current_date;
date_formate: 转换格式 select date_format('2021-12-27','yyyy-MM')
current_timestamp:当前的日期加时间带毫秒
to_date:抽取日期部分 select to_date('2021-12-23 13-59-56'); 
year:获取年            select year('2021-12-23 13-59-56');                                               
month:获取月                                                         
day:获取日                                                              
hour:获取时                                                            
minute:获取分                                                        
second:获取秒 
weekofyear:当前时间是一年中的第几周 select weekofyear('2021-12-31');
dayofmonth:当前时间是一个月中的第几天 select dayofmonth('2021-12-23');
months_between: 两个日期间的月份 select months_between('2021-12-23','2022-2-5');后面减前面
add_months:日期加减月 select add_months('2021-10-2',-2);
datediff:两个日期相差的天数 select datediff('2021-2-5','2021-12-6'); 前面减后面
date_add:日期加天数 select date_add('2021-8-8',5);
date_sub:日期减天数  select date_add('2021-8-8',-5);
last_day:日期的当月的最后一天 select last_day('2021-12-5');
取整类:
round: 四舍五入 select round(2.3);
ceil:  向上取整
floor: 向下取整 
字符串操作函数
upper: 转大写 select upper('ssss');
lower: 转小写
length: 长度 select length('ssss');
trim:  前后去空格 select trim('   ls   ');
lpad: 向左补齐,到指定长度 select lpad('ls',5,'@');
rpad:  向右补齐,到指定长度
regexp_replace:替换 select regexp_replace('ababab','b','c');
集合操作
size: 集合中元素的个数
map_keys: 返回map中的key
map_values: 返回map中的value 
array_contains: 判断array中是否包含某个元素
sort_array: 将array中的元素排序 

二、常用内置函数

1.空字段赋值

    NVL:给值为NULL的数据赋值,它的格式是NVL( value,default_value)。它的功能是如果value为NULL,则NVL函数返回default_value的值,否则返回value的值,如果两个参数都为NULL ,则返回NULL。
select id,nvl(id, -1) from stu; //如果id为NULL,则返回-1

2.case语句

具体格式:CASE WHEN THEN ELSE END

需求:

name

dept_id

sex

悟空

A

大海

A

宋宋

B

凤姐

A

婷姐

B

婷婷

B

得到:

+------------+-------+---------+
| t.dept_id  | male  | female  |
+------------+-------+---------+
| A          | 2     | 1       |
| B          | 1     | 2       |
+------------+-------+---------+

步骤:

select
    dept_id,
    case when '男' then 1 else 0 end male,
    case when '女' then 1 else 0 end female,
from emp_sex
+----------+-------+---------+
| dept_id  | male  | female  |
+----------+-------+---------+
| A        | 1     | 0       |
| A        | 1     | 0       |
| B        | 1     | 0       |
| A        | 0     | 1       |
| B        | 0     | 1       |
| B        | 0     | 1       |
+----------+-------+---------+

select 
    t.dept_id,
    sum(t.male) male,
    sum(t.female) female
from (select
    dept_id,
    case sex when '男' then 1 else 0 end,
    case sex when '女' then 1 else 0 end 
from emp_sex) t 
group by t.dept_id;

+------------+-------+---------+
| t.dept_id  | male  | female  |
+------------+-------+---------+
| A          | 2     | 1       |
| B          | 1     | 2       |
+------------+-------+---------+

select
    dept_id,
    sum(case sex when '男' then 1 else 0 end ) male,
    sum(case sex when '女' then 1 else 0 end ) female
from emp_sex
group by dept_id;

用if
select
  dept_id,
  sum(if(sex='男',1,0)) male,
  sum(if(sex='女',1,0)) female
from emp_sex
group by dept_id

3.行转列

函数:CONCAT(string A, string B) 连接字符串

         CONCAT_WS(separator, str1, str2,...) 用separator连接字符串 注:注意:CONCAT_WS must be "string or array<string>"

         COLLECT_SET() 去重,产生array类型字段

         COLLECT_LIST() 不去重,产生array类型字段

需求:

name

constellation

blood_type

孙悟空

白羊座

A

大海

射手座

A

宋宋

白羊座

B

猪八戒

白羊座

A

凤姐

射手座

A

苍老师

白羊座

B

得到:

射手座,A            大海|凤姐
白羊座,A            孙悟空|猪八戒
白羊座,B            宋宋|苍老师

步骤:

select
    concat(constellation,',',blood_type),
    name
from person_info

select
    t.a,
    concat_ws('|',collect_set(t.name))
from (select
concat(constellation,',',blood_type) a,
name
from person_info) t
group by t.a
+--------+----------+
|  t.a   |   _c1    |
+--------+----------+
| 射手座,A  | 大海|凤姐    |
| 白羊座,A  | 孙悟空|猪八戒  |
| 白羊座,B  | 宋宋|苍老师   |
+--------+----------+

select
 concat(constellation,',',blood_type),
 concat_ws('|',collect_list(name))
from person_info
group by concat(constellation,',',blood_type)

4.列转行

函数:

        Split(str, s):用分隔符s分割字符串str,转换成array。

        EXPLODE():将hive一列中复杂的array或者map结构拆分成多行。

        LATERAL VIEW

        用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias

        解释:lateral view用于和split, explode等UDTF一起使用,它能够将一行数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。

        lateral view首先为原始表的每行调用UDTF,UDTF会把一行拆分成一或者多行,lateral view再把结果组合,产生一个支持别名表的虚拟表。

需求:

movie

category

《疑犯追踪》

悬疑,动作,科幻,剧情

《Lie to me》

悬疑,警匪,动作,心理,剧情

《战狼2》

战争,动作,灾难

得到:

《疑犯追踪》      悬疑
《疑犯追踪》      动作
《疑犯追踪》      科幻
《疑犯追踪》      剧情
《Lie to me》   悬疑
《Lie to me》   警匪
《Lie to me》   动作
《Lie to me》   心理
《Lie to me》   剧情
《战狼2》        战争
《战狼2》        动作
《战狼2》        灾难

步骤:

select
    EXPLODE(split(category,','))
from movie_info
+------+
| col  |
+------+
| 悬疑   |
| 动作   |
| 科幻   |
| 剧情   |
| 悬疑   |
| 警匪   |
| 动作   |
| 心理   |
| 剧情   |
| 战争   |
| 动作   |
| 灾难   |
+------+

select 
movie
from movie_info

+--------------+
|    movie     |
+--------------+
| 《疑犯追踪》       |
| 《Lie to me》  |
| 《战狼2》        |
+--------------+

select
    movie,
    category_name
from movie_info
    lateral view explode(split(category,',')) tmp as category_name
where category_name = '悬疑';
    
+--------------+----------------+
|    movie     | category_name  |
+--------------+----------------+
| 《疑犯追踪》       | 悬疑             |
| 《Lie to me》  | 悬疑             |
+--------------+----------------+

select
    movie,
    category_name
from movie_info
    lateral view explode(split(category,',')) tmp as category_name;
    
+--------------+----------------+
|    movie     | category_name  |
+--------------+----------------+
| 《疑犯追踪》       | 悬疑             |
| 《疑犯追踪》       | 动作             |
| 《疑犯追踪》       | 科幻             |
| 《疑犯追踪》       | 剧情             |
| 《Lie to me》  | 悬疑             |
| 《Lie to me》  | 警匪             |
| 《Lie to me》  | 动作             |
| 《Lie to me》  | 心理             |
| 《Lie to me》  | 剧情             |
| 《战狼2》        | 战争             |
| 《战狼2》        | 动作             |
| 《战狼2》        | 灾难             |
+--------------+----------------+

5.窗口函数

        OVER():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变而变化。

        CURRENT ROW:当前行

        n PRECEDING:往前n行数据

        n FOLLOWING:往后n行数据

        UNBOUNDED:无边界

        UNBOUNDED PRECEDING 前无边界,表示从前面的起点,

        UNBOUNDED FOLLOWING后无边界,表示到后面的终点

        LAG(col,n,default_val):往前第n行数据

        LEAD(col,n, default_val):往后第n行数据

        FIRST_VALUE (col,true/false):当前窗口下的第一个值,第二个参数为true,跳过空值

        LAST_VALUE (col,true/false):当前窗口下的最后一个值第二个参数true,跳过空值

        NTILE(n):把有序窗口的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。注意:n必须为int类型。

语法

        函数+窗口  

        函数:代表的计算的逻辑

        窗口:表示函数的计算范围  把窗口数据给到函数做计算 
  函数+over([partition by ...] [order by ...] [窗口子句])  over表示开窗
          over 表示开窗 默认有一个窗口大小 就是所有数据
          partition by 表示根据字段再划分一个细窗口 相同字段进入同一个细窗口里面 每个窗口之间相互独立 窗口子句对于每个细窗口独立生效
          order by 表示窗口内按什么排序 如果只有over 表示直接最大窗口排序 如果有partition by 每个细窗口单独排序
  执行顺序
          1.over
          2.partition
          3.order by
          4.窗口子句
          5.函数

窗口子句默认值:当有order by 但是缺少窗口子句时,范围是上无边界到当前行

                            当order by 和 窗口子句都缺少时,范围是上无边界到下无边界

不支持窗口子句的函数

        rank dense_rank ntile row_number lag lead

注意:

一. 建表的时候    
        1.partitioned by 表示你创建的表为分区表
        2.clustered by 表示你创建表为分桶表
二. 查询语句里排序的四个by
        order by 表示全局排序
        distribute by 以什么分区 sort by 区内排序字段
        cluster by 表示分区排序
三.窗口函数的partition
        partition by 表示 更细窗口划分
        order by 窗口以什么排序

        distribute by sort by  相当于 partition by  order by

实例:

jack,2017-01-01,10
tony,2017-01-02,15
jack,2017-02-03,23
tony,2017-01-04,29
jack,2017-01-05,46
jack,2017-04-06,42
tony,2017-01-07,50
jack,2017-01-08,55
mart,2017-04-08,62
mart,2017-04-09,68
neil,2017-05-10,12
mart,2017-04-11,75
neil,2017-06-12,80
mart,2017-04-13,94

具体例子

(1)查询在2017年4月份购买过的顾客及总人数
select
    name,
    count(*) over(rows between UNBOUNDED PRECEDING and current row)
from business
where month(orderdate)=4
group by name;
+-------+-----------------+
| name  | count_window_0  |
+-------+-----------------+
| mart  | 1               |
| jack  | 2               |
+-------+-----------------+
(2)查询所有月购买过的顾客及总人数(不用窗口函数)
select
    date_format(orderdate,'yyyy-MM'),
    collect_set(name),
    size(collect_set(name))
from business
group by date_format(orderdate,'yyyy-MM');
+----------+------------------+------+
|   _c0    |       _c1        | _c2  |
+----------+------------------+------+
| 2017-01  | ["jack","tony"]  | 2    |
| 2017-02  | ["jack"]         | 1    |
| 2017-04  | ["jack","mart"]  | 2    |
| 2017-05  | ["neil"]         | 1    |
| 2017-06  | ["neil"]         | 1    |
+----------+------------------+------+
(3)查询顾客的购买明细及月购买总额
select
    name,
    orderdate,
    cost,
    sum(cost)over(partition by month(orderdate))
from business
+-------+-------------+-------+---------------+
| name  |  orderdate  | cost  | sum_window_0  |
+-------+-------------+-------+---------------+
| jack  | 2017-01-01  | 10    | 205           |
| jack  | 2017-01-08  | 55    | 205           |
| tony  | 2017-01-07  | 50    | 205           |
| jack  | 2017-01-05  | 46    | 205           |
| tony  | 2017-01-04  | 29    | 205           |
| tony  | 2017-01-02  | 15    | 205           |
| jack  | 2017-02-03  | 23    | 23            |
| mart  | 2017-04-13  | 94    | 341           |
| jack  | 2017-04-06  | 42    | 341           |
| mart  | 2017-04-11  | 75    | 341           |
| mart  | 2017-04-09  | 68    | 341           |
| mart  | 2017-04-08  | 62    | 341           |
| neil  | 2017-05-10  | 12    | 12            |
| neil  | 2017-06-12  | 80    | 80            |
+-------+-------------+-------+---------------+
(4)上述的场景, 将每个顾客的cost按照日期进行累加
select
    name,
    orderdate,
    cost,
    sum(cost)over(partition by name order by orderdate)
from business
+-------+-------------+-------+---------------+
| name  |  orderdate  | cost  | sum_window_0  |
+-------+-------------+-------+---------------+
| jack  | 2017-01-01  | 10    | 10            |
| jack  | 2017-01-05  | 46    | 56            |
| jack  | 2017-01-08  | 55    | 111           |
| jack  | 2017-02-03  | 23    | 134           |
| jack  | 2017-04-06  | 42    | 176           |
| mart  | 2017-04-08  | 62    | 62            |
| mart  | 2017-04-09  | 68    | 130           |
| mart  | 2017-04-11  | 75    | 205           |
| mart  | 2017-04-13  | 94    | 299           |
| neil  | 2017-05-10  | 12    | 12            |
| neil  | 2017-06-12  | 80    | 92            |
| tony  | 2017-01-02  | 15    | 15            |
| tony  | 2017-01-04  | 29    | 44            |
| tony  | 2017-01-07  | 50    | 94            |
+-------+-------------+-------+---------------+
(5)查询顾客购买明细以及上次的购买时间和下次购买时间
select
    name,
    orderdate,
    cost,
    lag(orderdate,1,'0000-00-00')over(partition by name order by orderdate),
    lead(orderdate,1,'9999-99-99')over(partition by name order by orderdate)
from business
+-------+-------------+-------+---------------+----------------+
| name  |  orderdate  | cost  | lag_window_0  | lead_window_1  |
+-------+-------------+-------+---------------+----------------+
| jack  | 2017-01-01  | 10    | 0000-00-00    | 2017-01-05     |
| jack  | 2017-01-05  | 46    | 2017-01-01    | 2017-01-08     |
| jack  | 2017-01-08  | 55    | 2017-01-05    | 2017-02-03     |
| jack  | 2017-02-03  | 23    | 2017-01-08    | 2017-04-06     |
| jack  | 2017-04-06  | 42    | 2017-02-03    | 9999-99-99     |
| mart  | 2017-04-08  | 62    | 0000-00-00    | 2017-04-09     |
| mart  | 2017-04-09  | 68    | 2017-04-08    | 2017-04-11     |
| mart  | 2017-04-11  | 75    | 2017-04-09    | 2017-04-13     |
| mart  | 2017-04-13  | 94    | 2017-04-11    | 9999-99-99     |
| neil  | 2017-05-10  | 12    | 0000-00-00    | 2017-06-12     |
| neil  | 2017-06-12  | 80    | 2017-05-10    | 9999-99-99     |
| tony  | 2017-01-02  | 15    | 0000-00-00    | 2017-01-04     |
| tony  | 2017-01-04  | 29    | 2017-01-02    | 2017-01-07     |
| tony  | 2017-01-07  | 50    | 2017-01-04    | 9999-99-99     |
+-------+-------------+-------+---------------+----------------+
(5)查询顾客每个月第一次的购买时间 和 每个月的最后一次购买时间
select
    name,
    orderdate,
    cost,
    first_value(orderdate)over(partition by name order by month(orderdate)),
    last_value(orderdate)over(partition by name order by month(orderdate))
from business
+-------+-------------+-------+-----------------------+----------------------+
| name  |  orderdate  | cost  | first_value_window_0  | last_value_window_1  |
+-------+-------------+-------+-----------------------+----------------------+
| jack  | 2017-01-05  | 46    | 2017-01-05            | 2017-01-01           |
| jack  | 2017-01-08  | 55    | 2017-01-05            | 2017-01-01           |
| jack  | 2017-01-01  | 10    | 2017-01-05            | 2017-01-01           |
| jack  | 2017-02-03  | 23    | 2017-01-05            | 2017-02-03           |
| jack  | 2017-04-06  | 42    | 2017-01-05            | 2017-04-06           |
| mart  | 2017-04-13  | 94    | 2017-04-13            | 2017-04-08           |
| mart  | 2017-04-11  | 75    | 2017-04-13            | 2017-04-08           |
| mart  | 2017-04-09  | 68    | 2017-04-13            | 2017-04-08           |
| mart  | 2017-04-08  | 62    | 2017-04-13            | 2017-04-08           |
| neil  | 2017-05-10  | 12    | 2017-05-10            | 2017-05-10           |
| neil  | 2017-06-12  | 80    | 2017-05-10            | 2017-06-12           |
| tony  | 2017-01-04  | 29    | 2017-01-04            | 2017-01-07           |
| tony  | 2017-01-02  | 15    | 2017-01-04            | 2017-01-07           |
| tony  | 2017-01-07  | 50    | 2017-01-04            | 2017-01-07           |
+-------+-------------+-------+-----------------------+----------------------+
(6)查询前20%时间的订单信息
select
    name,
    orderdate,
    cost,
    ntile(5)over(order by orderdate) 
from business
+-------+-------------+-------+-----------------+
| name  |  orderdate  | cost  | ntile_window_0  |
+-------+-------------+-------+-----------------+
| jack  | 2017-01-01  | 10    | 1               |
| tony  | 2017-01-02  | 15    | 1               |
| tony  | 2017-01-04  | 29    | 1               |
| jack  | 2017-01-05  | 46    | 2               |
| tony  | 2017-01-07  | 50    | 2               |
| jack  | 2017-01-08  | 55    | 2               |
| jack  | 2017-02-03  | 23    | 3               |
| jack  | 2017-04-06  | 42    | 3               |
| mart  | 2017-04-08  | 62    | 3               |
| mart  | 2017-04-09  | 68    | 4               |
| mart  | 2017-04-11  | 75    | 4               |
| mart  | 2017-04-13  | 94    | 4               |
| neil  | 2017-05-10  | 12    | 5               |
| neil  | 2017-06-12  | 80    | 5               |
+-------+-------------+-------+-----------------+

select
    t.name,
    t.orderdate,
    t.cost
from (select
    name,
    orderdate,
    cost,
    ntile(5)over(order by orderdate) n
from business
) t
where t.n =1
+---------+--------------+---------+
| t.name  | t.orderdate  | t.cost  |
+---------+--------------+---------+
| jack    | 2017-01-01   | 10      |
| tony    | 2017-01-02   | 15      |
| tony    | 2017-01-04   | 29      |
+---------+--------------+---------+
(7)求每个顾客的购买明细以及上一次购买和下一次购买花费的和
select
    name,
    orderdate,
    cost,
    sum(cost)over(partition by name order by orderdate rows between 1 PRECEDING and 1 FOLLOWING)-cost
from business
+-------+-------------+-------+------+
| name  |  orderdate  | cost  | _c3  |
+-------+-------------+-------+------+
| jack  | 2017-01-01  | 10    | 46   |
| jack  | 2017-01-05  | 46    | 65   |
| jack  | 2017-01-08  | 55    | 69   |
| jack  | 2017-02-03  | 23    | 97   |
| jack  | 2017-04-06  | 42    | 23   |
| mart  | 2017-04-08  | 62    | 68   |
| mart  | 2017-04-09  | 68    | 137  |
| mart  | 2017-04-11  | 75    | 162  |
| mart  | 2017-04-13  | 94    | 75   |
| neil  | 2017-05-10  | 12    | 80   |
| neil  | 2017-06-12  | 80    | 12   |
| tony  | 2017-01-02  | 15    | 29   |
| tony  | 2017-01-04  | 29    | 65   |
| tony  | 2017-01-07  | 50    | 29   |
+-------+-------------+-------+------+

RANK函数

        RANK() 排序相同时会重复,总数不会变

        DENSE_RANK() 排序相同时会重复,总数会减少

        ROW_NUMBER() 会根据顺序计算

需求:

name

subject

score

孙悟空

语文

87

孙悟空

数学

95

孙悟空

英语

68

大海

语文

94

大海

数学

56

大海

英语

84

宋宋

语文

64

宋宋

数学

86

宋宋

英语

84

婷婷

语文

65

婷婷

数学

85

婷婷

英语

78

得到:

name    subject score   rp      drp     rmp
孙悟空  数学    95      1       1       1
宋宋    数学    86      2       2       2
婷婷    数学    85      3       3       3
大海    数学    56      4       4       4
宋宋    英语    84      1       1       1
大海    英语    84      1       1       2
婷婷    英语    78      3       2       3
孙悟空  英语    68      4       3       4
大海    语文    94      1       1       1
孙悟空  语文    87      2       2       2
婷婷    语文    65      3       3       3
宋宋    语文    64      4       4       4

步骤:

select
    name,
    subject,
    score,
    rank()over(partition by subject order by score desc) r1,
    dense_rank()over(partition by subject order by score desc) r2,
    row_number()over(partition by subject order by score desc) r3
from score
+-------+----------+--------+-----+-----+-----+
| name  | subject  | score  | r1  | r2  | r3  |
+-------+----------+--------+-----+-----+-----+
| 孙悟空   | 数学       | 95     | 1   | 1   | 1   |
| 宋宋    | 数学       | 86     | 2   | 2   | 2   |
| 婷婷    | 数学       | 85     | 3   | 3   | 3   |
| 大海    | 数学       | 56     | 4   | 4   | 4   |
| 宋宋    | 英语       | 84     | 1   | 1   | 1   |
| 大海    | 英语       | 84     | 1   | 1   | 2   |
| 婷婷    | 英语       | 78     | 3   | 2   | 3   |
| 孙悟空   | 英语       | 68     | 4   | 3   | 4   |
| 大海    | 语文       | 94     | 1   | 1   | 1   |
| 孙悟空   | 语文       | 87     | 2   | 2   | 2   |
| 婷婷    | 语文       | 65     | 3   | 3   | 3   |
| 宋宋    | 语文       | 64     | 4   | 4   | 4   |
+-------+----------+--------+-----+-----+-----+

计算每个人的总分并排序
select
    name,
    sum(score)over(partition by name) s
from score
group by name, s
+-------+---------------+
| name  | sum_window_0  |
+-------+---------------+
| 大海    | 234           |
| 大海    | 234           |
| 大海    | 234           |
| 婷婷    | 228           |
| 婷婷    | 228           |
| 婷婷    | 228           |
| 孙悟空   | 250           |
| 孙悟空   | 250           |
| 孙悟空   | 250           |
| 宋宋    | 234           |
| 宋宋    | 234           |
| 宋宋    | 234           |
+-------+---------------+

//注意:Hive不允许直接访问非group by字段
select
    t.name,
    t.ss
from(select
    name,
    sum(score)over(partition by name) ss
from score
) t
group by t.name,t.ss

+---------+-------+
| t.name  | t.ss  |
+---------+-------+
| 大海      | 234   |
| 婷婷      | 228   |
| 孙悟空     | 250   |
| 宋宋      | 234   |
+---------+-------+

select
    d.t1,
    d.t2,
    rank()over(order by d.t2 desc rows between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING)
from (select
    t.name t1,
    t.ss t2
from(select
    name,
    sum(score)over(partition by name) ss
from score
) t
group by t.name,t.ss) d

+-------+-------+----------------+
| d.t1  | d.t2  | rank_window_0  |
+-------+-------+----------------+
| 孙悟空   | 250   | 1              |
| 宋宋    | 234   | 2              |
| 大海    | 234   | 2              |
| 婷婷    | 228   | 4              |
+-------+-------+----------------+

6.自定义函数以及举例

(1)UDF(User-Defined-Function)

        一进一出

(2)UDAF(User-Defined Aggregation Function)

        用户自定义聚合函数,多进一出

        类似于:count/max/min

(3)UDTF(User-Defined Table-Generating Functions)

        用户自定义表生成函数,一进多出

        如lateral view explode()

举例:

        自定义一个UDF实现计算给定基本数据类型的长度

    1.导入依赖

<dependencies>
		<dependency>
			<groupId>org.apache.hive</groupId>
			<artifactId>hive-exec</artifactId>
			<version>3.1.2</version>
		</dependency>
</dependencies>

2.编写代码

package com.hpu;


import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;

/**
 * @author LS
 * @date 2021/12/24 18:21
 * @description
 */
public class hive_udf extends GenericUDF {
    //判断传进来的参数的类型和长度 约定返回的数据类型
    @Override
    public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
        if (arguments.length != 1){
            throw new UDFArgumentLengthException("give one please");
        }
        if (!arguments[0].getCategory().equals(ObjectInspector.Category.PRIMITIVE)){
            throw new UDFArgumentTypeException(1, "i need primitive type arg");
        }
        return PrimitiveObjectInspectorFactory.javaIntObjectInspector;
    }
    //解决具体逻辑的
    @Override
    public Object evaluate(DeferredObject[] arguments) throws HiveException {
        Object o = arguments[0].get();
        if(o==null){
            return 0;
        }
        return o.toString().length();
    }
    //用于获取解释的字符串
    @Override
    public String getDisplayString(String[] strings) {
        return "";
    }
}

3.在hive端步骤

1.创建临时函数
(1)打成jar包上传到服务器/opt/module/hive/datas/udf.jar
(2)将jar包添加到hive的classpath,临时生效
    add jar /opt/module/hive/datas/udf.jar;
(3)创建临时函数与开发好的java class关联
    create temporary function my_len as "com.hpu.hive.hive_udf";
(4)即可在hql中使用自定义的临时函数
    select my_len(aaaa);
(5)删除临时函数
    drop  temporary function my_len;
	注意:临时函数只在当前会话内有效
2.创建永久函数
(1)创建永久函数
    create function my_len2 as "com.hpu.hive.hive_udf" using jar "hdfs://hadoop102:8020/udf/udf.jar";
(2)即可在hql中使用自定义的永久函数 
    select my_len(aaaa);
(3)删除永久函数 
    drop function my_len2;
注意:永久函数跟会话没有关系,创建函数的会话断了以后,其他会话也可以使用。
永久函数创建的时候,在函数名之前需要自己加上库名,如果不指定库名的话,会默认把当前库的库名给加上。
永久函数使用的时候,需要在指定的库里面操作,或者在其他库里面使用的话加上 库名.函数名

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值