Hive 内置函数

1.内置函数

  进入 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)

2.Hive函数分类

Hive 中的函数,分三种:

  1. UDF (一进一出,普通函数)
  2. UDTF (多进一出,聚合函数)
  3. UDAF (一进多出,炸裂函数)

指的是输入数据的行数

UDF函数:输入一行数据,返回一行数据。比如:upper(转大写)、substring(截取) 函数

UDTF函数:输入多行数据,返回一行数据,就是我们常用的聚合函数。比如:sum(求和)、avg(求平均数)函数

UDAF函数:输入一行数据,返回多行数据,又叫做炸裂函数。比如:explode(用于打散行,将一行的数据拆分成多行,它的参数必须为map或array)函数(炸裂函数:比如一行有很多单词,逗号分割,最后将单词通过逗号拆开,一个单词放一行,即输入一行输出多行)


如下图所示,通过命令:desc function extended 函数名;可以来查看函数是什么类型
在这里插入图片描述

3.常用函数介绍

由于博主有 MySQL 、Oracle 相关知识。此处部分函数的使用和 MySQL、Oracle 完全一致,就不在此过多描述

3.1 nvl

函数说明
  给值为 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

3.2 case when then else end

函数说明
  多条件判断函数,类似 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

3.3 concat相关函数

Ⅰ.concat

函数说明
  CONCAT(string A/col, string B/col…) 返回输入字符串连接后的结果,支持任意个输入字符串。【MySQL、Oracle中均有 concat 函数】

示例:

SELECT concat("Hello","----","World");   # 返回 Hello----World

Ⅱ.concat_ws

函数说明
  CONCAT_WS(separator, str1, str2,…) :它是一个特殊形式的 CONCAT()。第一个参数为参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间;

示例:

select concat_ws("-","Hello","World","HaHaHa");   #返回Hello-World-HaHaHa

注意:
   CONCAT_WS 中传入的参数,必须是 string字符串 或者 array<string>字符串数组传入 array<string>字符串数组,concat_ws 可配合 collect_set、collect_list 使用

3.4 collect_相关函数

数据:
在这里插入图片描述

Ⅰ.collect_set

函数说明
  collect_set 函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生 Array 类型字段。

示例:

# collect_set
select dept_no,collect_set(user_name) from user_info group by dept_no;

在这里插入图片描述

Ⅱ.collect_list

函数说明
  collect_list 与 collect_set 不同的是它不会去重。

示例:

#collect_list
select dept_no,collect_list(user_name) from user_info group by dept_no;

在这里插入图片描述

3.5 explode + lateral view

提示: 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

3.6 grouping sets 多维分析

使用 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));

查询结果:
在这里插入图片描述
5.聚合查询,使用grouping sets 和 group by 的对比图(摘自官方文档)
在这里插入图片描述

3.7 开窗函数

提示:MySQL 在 8.X 版本也引入了开窗函数,与 Hive 中使用一样。随便找了个 blog 了解一下吧。MySQL 8.x 开窗函数 blog

官方文档,参考:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+WindowingAndAnalytics

数据:
在这里插入图片描述

Ⅰ.over()大致介绍

说明:
   group by 可以根据某个字段对数据集进行分组。over() 也类似,可以指定字段。但是它和 group by 还是不同的。

不同点在于
  group by 按照某个字段分组,比如说部门id,那么只要 id 相同的就都在一个组中,聚合时会对组中所有数据进行聚合。
  over() 则不同,它可以指定窗口大小随着行的改变而改变,比如说 over 根据某个字段分组(此处说分组也不妥),它可以在组内开窗,再次指定哪些行分为一组。

Ⅱ.over() 括号中会使用到的几个关键词(如何使用参考下文3.1)

关键词含义
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;

运行结果:
在这里插入图片描111述
在这里插入图片描述
结果分析:

  为什么是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;

查询结果:>在这里插入图片描述

Ⅲ.通过几个需求来了解over()的使用:

1.查询在2017年4月份购买过的顾客及总人数
select 
   name,
   count(*) over ()
from 
   order_info
where 
   date_format(orderdate,'yyyy-MM') = '2017-04'
group by 
   name;

在这里插入图片描述

2.查询顾客的购买明细及月购买金额
select 
   name,
   orderdate,
   cost,
   sum(cost) over(partition by month(orderdate))
from
   order_info;

在这里插入图片描述

3.查询顾客的购买明细,将每个顾客的cost按照日期进行累加

备注:累加功能,在 over() 中加个 order by 即可

select 
   name,
   orderdate,
   cost,
   sum(cost) over(partition by name order by orderdate)
from
   order_info;

在这里插入图片描述

3.1 over 中的几个关键字使用介绍

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分组,当前行后面所有行做聚合
在这里插入图片描述

4.LAG查询每个顾客上次的购买时间

提示: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 与 Lag 正好反方向。功能一致

# lead 1行,为 null 使用本行的 orderdate
select 
    name,
    orderdate,
    lead(orderdate,1,orderdate) over(partition by name order by orderdate)
from 
    order_info;

在这里插入图片描述
② lead 往后2行

# lead 2行,为 null 使用本行的 orderdate
select 
    name,
    orderdate,
    lead(orderdate,2,orderdate) over(partition by name order by orderdate)
from 
    order_info;

在这里插入图片描述

5.查询前 20% 时间的订单信息

按时间排序,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

在这里插入图片描述

3.8 rank、dense_rank

提示:需要配合开窗函数 over() 使用。
MySQL 在 8.x版本也引入了开窗函数,就很容易实现类似 rank、dense_rank 的功能。

函数说明:
  rank 函数用于排序,排序相同时会重复,总数不会变。
  dense_rank 函数用于排序,排序相同时总数会减少。

举例:
  类似成绩排名。第一个人500分,第二个人500分。并列第一。第三个人499。说的就是他是第二名?还是第三名的问题。rank 总数不会变,排序后是 1、1、3dense_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;

在这里插入图片描述

3.9 row_number

提示:需要配合开窗函数 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 个函数。

4.自定义函数

  总有 Hive 内置函数解决不了的问题,就需要我们来自定义 Hive 函数了。常用来自定义的是 UDF、UDTF 函数。聚合函数 UDAF 基本已经都内置了。此处就重点介绍自定义UDF函数自定义UDTF函数

Hive 自定义函数,本文不做介绍,如需了解。跳转查看:https://blog.csdn.net/lzb348110175/article/details/117653668

下一篇:Hive自定义函数


博主写作不易,加个关注呗

求关注、求点赞,加个关注不迷路 ヾ(◍°∇°◍)ノ゙

我不能保证所写的内容都正确,但是可以保证不复制、不粘贴。保证每一句话、每一行代码都是亲手敲过的,错误也请指出,望轻喷 Thanks♪(・ω・)ノ

  • 5
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
一、关系运算: 4 1. 等值比较: = 4 2. 不等值比较: 4 3. 小于比较: < 4 4. 小于等于比较: 5 6. 大于等于比较: >= 5 7. 空值判断: IS NULL 5 8. 非空判断: IS NOT NULL 6 9. LIKE比较: LIKE 6 10. JAVA的LIKE操作: RLIKE 6 11. REGEXP操作: REGEXP 7 二、数学运算: 7 1. 加法操作: + 7 2. 减法操作: - 7 3. 乘法操作: * 8 4. 除法操作: / 8 5. 取余操作: % 8 6. 位与操作: & 9 7. 位或操作: | 9 8. 位异或操作: ^ 9 9.位取反操作: ~ 10 三、逻辑运算: 10 1. 逻辑与操作: AND 10 2. 逻辑或操作: OR 10 3. 逻辑非操作: NOT 10 四、数值计算 11 1. 取整函数: round 11 2. 指定精度取整函数: round 11 3. 向下取整函数: floor 11 4. 向上取整函数: ceil 12 5. 向上取整函数: ceiling 12 6. 取随机数函数: rand 12 7. 自然指数函数: exp 13 8. 以10为底对数函数: log10 13 9. 以2为底对数函数: log2 13 10. 对数函数: log 13 11. 幂运算函数: pow 14 12. 幂运算函数: power 14 13. 开平方函数: sqrt 14 14. 二进制函数: bin 14 15. 十六进制函数: hex 15 16. 反转十六进制函数: unhex 15 17. 进制转换函数: conv 15 18. 绝对值函数: abs 16 19. 正取余函数: pmod 16 20. 正弦函数: sin 16 21. 反正弦函数: asin 16 22. 余弦函数: cos 17 23. 反余弦函数: acos 17 24. positive函数: positive 17 25. negative函数: negative 17 五、日期函数 18 1. UNIX时间戳转日期函数: from_unixtime 18 2. 获取当前UNIX时间戳函数: unix_timestamp 18 3. 日期转UNIX时间戳函数: unix_timestamp 18 4. 指定格式日期转UNIX时间戳函数: unix_timestamp 18 5. 日期时间转日期函数: to_date 19 6. 日期转年函数: year 19 7. 日期转月函数: month 19 8. 日期转天函数: day 19 9. 日期转小时函数: hour 20 10. 日期转分钟函数: minute 20 11. 日期转秒函数: second 20 12. 日期转周函数: weekofyear 20 13. 日期比较函数: datediff 21 14. 日期增加函数: date_add 21 15. 日期减少函数: date_sub 21 六、条件函数 21 1. If函数: if 21 2. 非空查找函数: COALESCE 22 3. 条件判断函数:CASE 22 4. 条件判断函数:CASE 22 七、字符串函数 23 1. 字符串长度函数:length 23 2. 字符串反转函数:reverse 23 3. 字符串连接函数:concat 23 4. 带分隔符字符串连接函数:concat_ws 23 5. 字符串截取函数:substr,substring 24 6. 字符串截取函数:substr,substring 24 7. 字符串转大写函数:upper,ucase 24 8. 字符串转小写函数:lower,lcase 25 9. 去空格函数:trim 25 10. 左边去空格函数:ltrim 25 11. 右边去空格函数:rtrim 25 12. 正则表达式替换函数:regexp_replace 26 13. 正则表达式解析函数:regexp_extract 26 14. URL解析函数:parse_url 26 15. json解析函数:get_json_object 27 16. 空格字符串函数:space 27 17. 重复字符串函数:repeat 27 18. 首字符ascii函数:ascii 28 19. 左补足函数:lpad 28 20. 右补足函数:rpad 28 21. 分割字符串函数: split 28 22. 集合查找函数: find_in_set 29 八、集合统计函数 29 1. 个数统计函数: count 29 2. 总和统计函数: sum 29 3. 平均值统计函数: avg 30 4. 最小值统计函数: min 30 5. 最大值统计函数: max 30 6. 非空集合总体变量函数: var_pop 30 7. 非空集合样本变量函数: var_samp 31 8. 总体标准偏离函数: stddev_pop 31 9. 样本标准偏离函数: stddev_samp 31 10.中位数函数: percentile 31 11. 中位数函数: percentile 31 12. 近似中位数函数: percentile_approx 32 13. 近似中位数函数: percentile_approx 32 14. 直方图: histogram_numeric 32 九、复合类型构建操作 32 1. Map类型构建: map 32 2. Struct类型构建: struct 33 3. array类型构建: array 33 十、复杂类型访问操作 33 1. array类型访问: A[n] 33 2. map类型访问: M[key] 34 3. struct类型访问: S.x 34 十一、复杂类型长度统计函数 34 1. Map类型长度函数: size(Map) 34 2. array类型长度函数: size(Array) 34 3. 类型转换函数 35
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

扛麻袋的少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值