进入 hive 客户端,通过命令show functions
来查看系统内置的函数,默认内置了 289 个函数。通过命令desc function 函数名
可以查看自带函数的描述,通过命令desc function extended 函数名
可查看自带函数详细的用法(附带Example)。如下所示:
# 1.查看函数描述
hive (test)> desc function upper;
OK
tab_name
upper(str) - Returns str with all characters changed to uppercase
Time taken: 0.014 seconds, Fetched: 1 row(s)
# 2.查看函数详细用法
hive (test)> desc function extended upper;
OK
tab_name
upper(str) - Returns str with all characters changed to uppercase
Synonyms: ucase
Example:
> SELECT upper('Facebook') FROM src LIMIT 1;
'FACEBOOK'
Function class:org.apache.hadoop.hive.ql.udf.generic.GenericUDFUpper
Function type:BUILTIN
Time taken: 0.066 seconds, Fetched: 7 row(s)
Hive 中的函数,分三种:
(一进一出,普通函数)
(多进一出,聚合函数)
(一进多出,炸裂函数)
一
和多
指的是输入数据的行数
。
UDF函数:输入一行数据,返回一行数据。比如:upper(转大写)、substring(截取) 函数
UDTF函数:输入多行数据,返回一行数据,就是我们常用的聚合函数。比如:sum(求和)、avg(求平均数)函数
UDAF函数:输入一行数据,返回多行数据,又叫做炸裂函数。比如:explode(用于打散行,将一行的数据拆分成多行,它的参数必须为map或array)函数(炸裂函数:比如一行有很多单词,逗号分割,最后将单词通过逗号拆开,一个单词放一行,即输入一行输出多行)
由于博主有 MySQL 、Oracle 相关知识。此处部分函数的使用和 MySQL、Oracle 完全一致,就不在此过多描述
函数说明:
给值为 NULL 的数据赋值,它的格式是NVL( value,default_value)
。它的功能是如果 value 为 NULL,则 NVL 函数返回 default_value 的值,否则返回 value 的值,如果两个参数都为 NULL ,则返回 NULL。【Oracle 中也有 NVL 函数】。
示例:select nvl(null,'默认值'); #返回默认值 select nvl("111","222"); #返回111 select nvl(100+100,"222"); #返回200
函数说明:
多条件判断函数,类似 Java 中的 if else 语句
。condition是一个返回布尔类型的表达式,如果表达式返回true,则整个函数返回相应result的值,如果表达式皆为false,则返回 ElSE 后 result 的值,如果省略了 ELSE 子句,则返回 NULL。【MySQL、Oracle 中均有 case when then else end 函数】
格式:CASE WHEN condition THEN result [WHEN...THEN...] ELSE result END
函数说明:
CONCAT(string A/col, string B/col…) 返回输入字符串连接后的结果,支持任意个输入字符串。【MySQL、Oracle中均有 concat 函数】
示例:SELECT concat("Hello","----","World"); # 返回 Hello----World
函数说明:
CONCAT_WS(separator, str1, str2,…) :它是一个特殊形式的 CONCAT()。第一个参数为参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间;
示例:select concat_ws("-","Hello","World","HaHaHa"); #返回Hello-World-HaHaHa
注意:
CONCAT_WS 中传入的参数,必须是string字符串
或者array
。传入 array字符串数组 字符串数组,concat_ws 可配合 collect_set、collect_list 使用 。
函数说明:
collect_set 函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生 Array 类型字段。
示例:# collect_set select dept_no,collect_set(user_name) from user_info group by dept_no;
函数说明:
collect_list 与 collect_set 不同的是它不会去重。
示例:#collect_list select dept_no,collect_list(user_name) from user_info group by dept_no;
提示: explode 是 UDTF函数,UDTF函数通常需要配合 lateral view 侧写表使用。
函数说明:
explode(col):将一行数据转换成列数据,可以用于array和map类型的数据。就是将 hive 一行中复杂的array或者map结构拆分成多行。
数据:
需求:
将电影分类中的数组数据展开。结果如下:
SQL:# 表名.* 方式 select movie, category_name.* from movie_info lateral view explode(split(category,'/')) category_name; # 列名方式 select movie, category_name from movie_info lateral view explode(split(category,'/')) movie_info_tmp as category_name;
分析:
如果使用select movie,explode(split(category,'/')) from movie_info;
则会报错:UDTF’s are not supported outside the SELECT clause, nor nested in expressions
原因:
当使用UDTF函数的时候,hive只允许对拆分字段进行访问。
正确命令:select explode(split(category,'/')) from movie_info;
错误命令:select movie,explode(split(category,'/')) from movie_info;
如果想访问除了拆分字段以外 的字段,怎么办呢?
用lateral view侧视图! 官方文档,参考:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+LateralView
lateral view为侧视图,意义是为了配合UDTF函数来使用,把某一行数据拆分成多行数据。不加 lateral view 的UDTF只能提取单个字段拆分,并不能塞回原来数据表中。加上lateral view就可以将拆分的单个字段数据与原始表数据关联上。explode 只炸裂一个列,直接炸裂即可。如果炸裂的同时,还需要原表相关的字段,就需要加 lateral view 侧写表了
注意:在使用 lateral view 的时候需要指定视图别名和生成的新列别名
【参考自:https://blog.csdn.net/u011110301/article/details/104198588】
使用 grouping sets 对数据进行多维度分析。如何使用 grouping sets 可参考官方文档:Enhanced Aggregation, Cube, Grouping and Rollup
1.需求:
①查看公司的总人数
②查看公司男性多少人,女性多少人
③查看公司每个部门有多少人
④查看公司每个部门男性、女性有多少人
2.数据如下:
3.基础SQL语句查询
①查看公司的总人数select count(*) from db_user;
②查看公司男性多少人,女性多少人
select user_sex, count(*) from db_user group by user_sex;
③查看公司每个部门有多少人
select dept_no, count(*) from db_user group by dept_no;
④查看公司每个部门男性、女性有多少人
select dept_no, user_sex, count(*) from db_user group by dept_no, user_sex;
4.使用 GROUPING SETS 一个语句即可完成!!!!
select dept_no, user_sex, count(*) from db_user group by dept_no,user_sex grouping sets ((),user_sex,dept_no,(user_sex,dept_no));
提示:MySQL 在 8.X 版本也引入了开窗函数,与 Hive 中使用一样。随便找了个 blog 了解一下吧。MySQL 8.x 开窗函数 blog
官方文档,参考:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+WindowingAndAnalytics
数据:
说明:
group by 可以根据某个字段对数据集进行分组。over() 也类似,可以指定字段。但是它和 group by 还是不同的。
不同点在于:
group by 按照某个字段分组,比如说部门id,那么只要 id 相同的就都在一个组中,聚合时会对组中所有数据进行聚合。
over() 则不同,它可以指定窗口大小随着行的改变而改变,比如说 over 根据某个字段分组(此处说分组也不妥),它可以在组内开窗,再次指定哪些行分为一组。
关键词 含义 PARTITION BY 以某个字段分区 ORDER BY 用于排序,配合聚合函数可实现累加 CURRENT ROW 当前行 n PRECEDING 往前 n 行数据 n FOLLOWING 往后 n 行的数据 UNBOUNDED 起点
UNBOUNDED PRECEDING 表示从前面的起点
UNBOUNDED FOLLOWING 表示到后面的终点LAG(col,n,default_val) 往前第 n 行数据【col 字段,n 往前推n行,default_val 往前推的n行,如果该行为空,使用default_val字段】 LEAD(col,n,default_val) 往后第 n 行数据 【col 字段,n 往前推n行,default_val 往前推的n行,如果该行为空,使用default_val字段】 FIRST_VALUE 这最多需要两个参数。 第一个参数是您想要第一个值的列,第二个(可选)参数必须是默认值为 false 的布尔值。 如果设置为 true 则跳过空值 LAST_VALUE 这最多需要两个参数。 第一个参数是您想要最后一个值的列,第二个(可选)参数必须是默认为 false 的布尔值。 如果设置为 true 则跳过空值。 NTILE(n) 把有序窗口的行,分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回慈航所属的组的编号。注意:n必须为 int 类型 提示:这几个关键字可以非常方便在开窗中对行数的控制。在下面的【需求 3.1 中会有使用到】,点击链接到 3.1 查看 →→To 3.1。你也可以参见官方文档示例:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+WindowingAndAnalytics
通过案例来了解一下over()的含义
案例一:over()存在的意义# 这个SQL是会直接报错的,因为使用count聚合函数,却没有 group by name; select name,count(name) from order_info;
# 加个 over() 在聚合函数后,在hive中就能够正常运行了。 select name,count(name) over() from order_info;
运行结果:
结果分析:
为什么是14呢?因为库中一共就有14条记录。
over() 在 group by 查询之后生效。我们执行select name from order_info;
会有14条记录。over() 即开窗的意思,over() 括号中没有限制条件,即代表将select name from order_info;
的14条记录作为窗口数据集,count(name) 就是对窗口里面的数据集进行 count 计算。select name 有14条数据,返回数据就为14条,count(name) 就是对 over() 窗口中的数据集计算,所以14条数据的 count(name) 都是14。
总结:
over() 开窗,窗口中的数据就是除聚合函数外查询到的数据。本例即:select name from order_info;
会有14条记录,count(name)就是对窗口中的数据求 count,就是 14 咯。
案例二:over()分区使用# over() 指定按照 name 分区 select name, count(name) over(partition by name) from order_info;
select name, count(*) over () from order_info where date_format(orderdate,'yyyy-MM') = '2017-04' group by name;
select name, orderdate, cost, sum(cost) over(partition by month(orderdate)) from order_info;
备注:累加功能,在 over() 中加个 order by 即可。
select name, orderdate, cost, sum(cost) over(partition by name order by orderdate) from order_info;
①
sum(cost) over(partition by name order by orderdate)
按name分组,组内数据累加
②sum(cost) over(partition by name order by orderdate
rows between UNBOUNDED PRECEDING and CURRENT ROW) 按name分组,由起点到当前行的聚合,与①一样,①默认也是起点到当前行的聚合
③sum(cost) over(partition by name order by orderdate
rows between 1 PRECEDING and CURRENT ROW) 按name分组,当前行与前面1行做聚合
④sum(cost) over(partition by name order by orderdate
rows between 1 PRECEDING and 1 FOLLOWING) 按name分组,当前行与前面1行与后面一行做聚合
⑤sum(cost) over(partition by name order by orderdate
rows between CURRENT ROW and 1 FOLLOWING) 按name分组,当前行与后面1行做聚合
⑤sum(cost) over(partition by name order by orderdate
rows between CURRENT ROW and UNBOUNDED FOLLOWING) 按name分组,当前行与后面所有行做聚合
提示:lag(col,n,default_val): 【col 字段,n 往前推n行,default_val 往前推的n行,如果改行为空,使用default_val字段】
① Lag 将前n条数据整体往下瞬移的意思。可以做页面访问轨迹。比如:从【A页面 > B页面 > C页面】访问select name, orderdate, (lag(orderdate,1,orderdate) over(partition by name order by orderdate)) upPurchaseTime from order_info;
# lead 1行,为 null 使用本行的 orderdate select name, orderdate, lead(orderdate,1,orderdate) over(partition by name order by orderdate) from order_info;
# lead 2行,为 null 使用本行的 orderdate select name, orderdate, lead(orderdate,2,orderdate) over(partition by name order by orderdate) from order_info;
按时间排序,20%即分成5个组,取第一个组的数据,使用到 ntile(n) 配合 over()完成
select
tb.name,
tb.orderdate,
tb.cose
from (
select
name,
orderdate,
cost,
ntile(5) over(order by orderdate) groupId
from
order_info;
) tb
where
tb.groupId = 1
提示:需要配合开窗函数 over() 使用。
MySQL 在 8.x版本也引入了开窗函数,就很容易实现类似 rank、dense_rank 的功能。
函数说明:
rank 函数用于排序,排序相同时会重复,总数不会变。
dense_rank 函数用于排序,排序相同时总数会减少。
举例:
类似成绩排名。第一个人500分,第二个人500分。并列第一。第三个人499。说的就是他是第二名?还是第三名的问题。rank 总数不会变,排序后是 1、1、3;dense_rank 总数则会减少,排序后是1、1、2
数据:
示例:# rank 排序后总数不会变,排序后是 1、1、3 select name, grade, rank() over(order by grade desc) from grade_info;
# dense_rank 总数则会减少,排序后是1、1、2 select name, grade, dense_rank() over(order by grade desc) from grade_info;
提示:需要配合开窗函数 over() 使用
MySQL 在 8.x版本也引入了开窗函数,就很容易实现类似 row_number 的功能。如果没有开窗函数,就比较复杂了,可参考:MySQL语句练习50题
函数说明:
row_number 函数,是给每一行添加一个编号,编号从1 开始,与 Oracle 中的 ROWNUM 差不多。
数据:
使用 3.7 数据
示例:select name, grade, row_number() over() from grade_info;
提示:
其他没介绍的内置函数,自行研究吧。通过命令show functions
来查看系统内置的函数,默认内置了 289 个函数。
总有 Hive 内置函数解决不了的问题,就需要我们来自定义 Hive 函数了。常用来自定义的是 UDF、UDTF 函数。聚合函数 UDAF 基本已经都内置了。此处就重点介绍
自定义UDF函数
和自定义UDTF函数
Hive 自定义函数,本文不做介绍,如需了解。跳转查看:https://blog.csdn.net/lzb348110175/article/details/117653668
下一篇:Hive自定义函数
博主写作不易,加个关注呗
求关注、求点赞,加个关注不迷路 ヾ(◍°∇°◍)ノ゙
我不能保证所写的内容都正确,但是可以保证不复制、不粘贴。保证每一句话、每一行代码都是亲手敲过的,错误也请指出,望轻喷 Thanks♪(・ω・)ノ