Hive函数
Posted 凉西瓜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hive函数相关的知识,希望对你有一定的参考价值。
文章目录
UDF: 一进一出
UDAF: 多进一出
UDTF: 一进多出
(“多” 指的是输入数据的行数。)
一、系统内置函数
- 查看系统自带的函数
show functions;
- 显示自带的函数的用法
desc function upper;
- 详细显示自带的函数的用法
desc function extended upper;
二、常用内置函数
空字段赋值 NVL
NVL(value,default_value) :
给值为NULL的数据赋值。它的功能是如果value为NULL,则NVL函数返回default_value的值,否则返回value的值,如果两个参数都为NULL ,则返回NULL
(default_value可以是一个值,也可以是别的字段)
CASE WHEN THEN ELSE END
- 需求:统计不同部门男女各多少人。结果应该如下图所示
- 查询语句:
select
dept_id,
sum(case sex when '男' then 1 else 0 end) male_count,
sum(case sex when '女' then 1 else 0 end) female_count
from
emp_sex
group by
dept_id;
多列变一列(列转列)
1)CONCAT(string A/col, string B/col…): 返回输入字符串连接后的结果,支持任意个输入字符串;
2)CONCAT_WS(separator, str1, str2,…): 它是一个特殊形式的 CONCAT()。第一个参数是分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间;
注意: CONCAT_WS must be "string or array
3)COLLECT_SET(col): 函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段。(多进一出,udaf函数)
注意:COLLECT_LIST(col)则不去重汇总,也产生array类型字段
一行变多行(行转行)
- EXPLODE(col): 将hive一列中复杂的array或者map结构拆分成多行。
如:
查询:
select explode(split(category,',')) from movie_info;
将 category 中的多个词拆分,得到:
select movie, explode(split(category,‘,’)) from movie_info; 会报错
要加上 movie 列则需要用以下函数:
- LATERAL VIEW:
LATERAL VIEW udtf(expression) tableAlias AS columnAlias
用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。
查询:
SELECT
movie,category_name
FROM movie_info
LATERAL VIEW explode(split(category,",")) movie_info_tmp AS category_name;
得到:
窗口函数
函数介绍
OVER():
指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的改变而变化。
写在 over() 里面的函数,用来限定分组的行数:
CURRENT ROW: 当前行
n PRECEDING: 往前n行数据
n FOLLOWING: 往后n行数据
UNBOUNDED: 起点
- UNBOUNDED PRECEDING 表示从前面的起点,
- UNBOUNDED FOLLOWING 表示到后面的终点
写在 over() 前面的函数:
LAG(col,n,default_val): 往前第n行数据
LEAD(col,n, default_val): 往后第n行数据
NTILE(n):
把有序窗口的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。注意:n必须为int类型。
按需求查询数据
原数据:
name,orderdate,cost
需求1:查询在2017年4月份购买过的顾客及总人数
select name, count(*) over ()
from business
where substring(orderdate,0,7) = '2017-04'
group by name;
结果:
需求2:查询顾客的 购买明细 及 月购买总额
select name, orderdate, cost, sum(cost) over(partition by name, month(orderdate))
from business
月份函数month()
需求3:上述的场景, 将每个顾客的cost按照日期进行累加
写法一:
select name, orderdate, sum(cost) over(partition by name order by orderdate)
from business
写法二:
select name, orderdate, sum(cost) over(partition by name order by orderdate rows between unbounded preceding and current row)
from business
根据文档:When ORDER BY is specified with missing WINDOW clause, the WINDOW specification defaults to RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.
拓展:上述场景,将每个顾客的cost按照前一条、当前和后一条相加
select name, orderdate, sum(cost) over(partition by name order by orderdate rows between 1 preceding and 1 following)
from business
注意:rows 必须跟在 order by 子句之后,对排序的结果进行限制,使用固定的行数来限制分区中的数据行数量
拓展:当排序值相同时:有一个只有一列 id 值的表,对其做以下查询
select id, sum(id) over(order by id)
from table1;
结果:
id值一样的,被认为是同一个窗口
需求4:查看顾客上次的购买时间
select name, orderdate, lag(orderdate,1, '1970-01-01') over(patition by name order by orderdate)
from business
需求5:查询前20%时间的订单信息
select name, orderdate, cost
from
(select name, orderdate, cost, ntile(5) over(order by orderdate) groupid
from business) t1
where groupid = 1;
Rank
RANK(): 排序相同时会重复,总数不会变
1 1 3
DENSE_RANK(): 排序相同时会重复,总数会减少
1 1 2
ROW_NUMBER() : 会根据顺序计算
1 2 3
原数据:
需求:计算每门学科成绩排名
select *, rank() over(partition by subject order by score desc)
from score
扩展:求出每门学科前三名的学生
select
name,
subject,
score
from
(select *, rank() over(partition by subject order by score desc) rk
from score) t1
where rk <= 3;
常用日期函数
unix_timestamp
from_unixtime
current_date
current_timestamp
to_date
year
month
day
hour
minute
second
weekofyear
dayofmonth
months_between
add_months
datediff
date_add
date_sub
last_day
date_format
常用取整函数
round:四舍五入
ceil:向上取整
floor:向下取整
常用字符串操作函数
upper
lower
length
trim
lpad
rpad
regexp_replace
集合操作
size
map_keys
map_values
array_contains
sort_array
以上是关于Hive函数的主要内容,如果未能解决你的问题,请参考以下文章
Hive count(distinct c1) ,不包含NULL的总数
hive对有null值的列进行avg,sum,count等操作时会不会过滤null值
编写Spark的UDF函数解决Hive表大数bigintdoublefloatdecimal等转字符串string时出现的科学计数法问题Java