hive函数

函数

Hive的函数分为两大类∶内置函数(Built-in Functions )、用户定义函数UDF (User-Defined Functions ) .

内置函数可分为︰数值类型函数、日期类型函数、字符串类型函数、集合函数、条件函数等;

用户定义函数根据输入输出的行数可分为3类:UDF、UDAF、UDTF。

  • UDF:普通函数,一进一出
  • UDAF:聚合函数,多进一出
  • UDTF:表生成函数,一进多出

在这里插入图片描述

UDF分类标准本来针对的是用户自己编写开发实现的函数。UDF分类标准可以扩大到Hive的所有函数中︰包括内置函数和用户自定义函数。

查看所有函数

show functions ;

查看指定函数信息

-- 查看count函数信息
desc function count;
desc function extended count;

函数API文档

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF#LanguageManualUDF-Built-inFunctions

1 字符串函数

在这里插入图片描述

---------String Functions字符串函数-— —---------
select concat("liu", "yan")
-- 带分隔符字符串连接函数:concat_ws(separator,[string|array(string)]+)
select concat_ws('.', 'www', array('51doit', 'com'));
--字符串截取函数: substr(str, pos[, len])或者substring(str, pos[,len])
select substr("angelababy", -2); --pos是从1开始的索引,如果为负数则倒着数
select substr("angelababy", 2, 2);
-- 正则表达式替换函数: regexp_replace(str, regexp,rep)
select regexp_replace('100-200', '(\\d+)', 'num');
-- 正则表达式解析函数:regexp_extract(str,regexp[, idx]) 提取正则匹配到的指定组内容
select regexp_extract('100-200', '(\\d+)-(\\d+)', 2);
-- URL解析函数: parse_url 
select parse_url('http://www.51doit.com/path/p1.php?query=1', 'HOST');
select parse_url('http://www.51doit.com/path/p1.php?query=1', 'PATH');
select parse_url('http://www.51doit.com/path/p1.php?query=1', 'QUERY');
--分割字符串函数: split(str, regex)
select split('apache hive', '\\s+');
--json解析函数: get_json_object(json_txt, path)  
-- $ 获取对象
select get_json_object(
               '[{"name":"柳岩","sex":"女","age":"38"},{"name":"唐嫣","sex":"女","age":"18"}]', '$.[0]');
select get_json_object(
               '[{"name":"柳岩","sex":"女","age":"38"},{"name":"唐嫣","sex":"女","age":"18"}]', '$[0].name');

------------------------------------------以下自行练习------------------------------------------
-- 字符串长度函数: length(str / binary)
select length("I Love Hive");
-- 字符串反转函数: reverse
select reverse("I Love Hive");
-- 字符串连接函数:concat(stri, str2, ... strN)
-- 字符串转大写函数: upper , ucase
select upper("I Love Hive");
select ucase("I Love Hive");
-- 字符串转小写函数:lower , Lcase
select lower("I Love Hive");
select lcase("I Love Hive");
-- 去空格函数: trim去除左右两边的空格
select trim(" I Love Hive ");
-- 左边去空格函数: ltrim
select ltrim(" I Love Hive ");
-- 右边去空格函数:rtrim
select ltrim(" I Love Hive ");
-- 空格字符串函数: space(n)返回指定个数空格
select space(4);
-- 重复字符串函数:repeat(str, n)重复str字符串n
select repeat("I Love Hive", 2);
-- 首字符ascii函数: ascii
select ascii("angela");
--a对应ASCII 97
--左补足函数:lpad
select lpad('hi', 5, '*');
--右补足函数: rpad
select rpad('hi', 5, '*');
--集合查找函数:find_in_set(str ,str_array)  返回str的位置 从1开始
select find_in_set('b', 'abc,b,ab,c,def');

2 日期函数

在这里插入图片描述

-- 当前日期
select current_date();
-- 获取当前时问歌:current_timestamp
-- 同一查询中对current_timestamp 的所有调用均返回相同的值。
select current_timestamp();
-- 获取当前UNIX时间戳函数:unix_timestamp
select unix_timestamp();
-- 日期转UNIX时问戳函数: unix_timestamp
select unix_timestamp("2022-08-13 19:08:03");
-- 指定格式日期转UNIX时间戳函数: unix_timestamp
select unix_timestamp('20220813 19:08:03', 'yyyyMMdd HH:mm:ss');
--UNIX时间戳转日期函数:from_unixtime
select from_unixtime(1660417683);
select from_unixtime(0, 'yyyy-MM-dd HH:mm:ss');
--日期比较函数; datediff日期格式要求'yyyy-MN-dd HH:mm:ss ' or 'yyyy-MM-dd '
select datediff('2022-08-08', '2022-08-10');
-- 日期增加函数: date_add
select date_add('2022-08-08', 10);
--日期减少函数: date_sub
select date_sub('2012-08-08', 10);
-- 日期格式化
select date_format('2022-08-13 19:08:03','yyyy/MM/dd');
------------------------------------------以下自行练习------------------------------------------
-- 抽取日期函数:to_date
select to_date('2022-08-13 19:08:03');
-- 获取年:year
select year('2022-08-13 19:08:03');
-- 获取月:month
select month('2022-08-13 19:08:03');
-- 获取日:day
select day('2022-08-13 19:08:03');
-- 获取时:hour
select hour('2022-08-13 19:08:03');
-- 获取分:minute
select minute('2022-08-13 19:08:03');
-- 获取秒:second
select second('2022-08-13 19:08:03');
-- 获取周:weekofyear 指定年份的第多少周
select weekofyear('2022-08-13 19:08:03');

3 数学函数

在这里插入图片描述

-- 四舍五入: round返回double类型的整数值部分(四舍五入)
select round(3.1415926);
select round(3.1415926, 2);
-- 向下取整函数:floor
select floor(3.1415926);
select floor(-3.1415926);
-- 向上取整函数: ceil
select ceil(3.1415926);
select ceil(-3.1415926);
--取随机数函数: rand每次执行都不一样返回一个0到1范围内的随机数
select rand();
-- 在同一个查询中保证同一个随机数
select rand(10);

-- 二进制
select bin(100);
-- 转换进制  conv(num,现在进制,要转换的进制)
select conv(11, 10, 2);
-- 绝对值
select abs(-100);

4 集合函数

在这里插入图片描述

-- 创建map集合 map(k1,v1,k2,v2...)
select map('zhangsan', '18', 'lisi', '28');
-- 获取map所有的键
select map_keys(map('zhangsan', '18', 'lisi', '28'));
-- 获取map所有的值
select map_values(map('zhangsan', '18', 'lisi', '28'));
-- 获取map指定键的值
select map('zhangsan', '18', 'lisi', '28')['zhangsan'];
-- 获取map的长度
select size(map('zhangsan', '18', 'lisi', '28'));
-- 创建数组 array(值1,值2,值3);
select array(1, 3, 5, 6);
-- 数组取值
select array(3, 3, 5, 6)[0];
-- 数组长度
select size(array(3, 3, 5, 6));
-- 数组排序
select sort_array(`array`(13, 7, 5, 2, 1));
-- 创建结构体
select struct('liuyan', 38);
-- 取值
select struct('liuyan', 38).col2;

5 条件判断函数

在这里插入图片描述

-- if判断 类似java三元表达式  if(boolean testCondion,T valueTrue,T valueFalse)
select if(1 == 1, 'a', 'b');
-- 判断是否为空: isnull 空返回true 非空返回false
select isnull(null);
select isnull(10);
-- 判断是否非空:isnotnull  不是null返回true 是null返回false
select isnotnull(null);
select isnotnull(10);
-- nvl(T value, T defaultValue) 判断value是否为空 非空返回value, 是空返回defaultValue
select nvl("aa", "bb");
select nvl(null, "bb");
--coalesce(v1,v2,v3,v4...)返回第一个非空的值 如果都为null返回null
select coalesce(null, null, null, null);
select coalesce(null, null, 1, 2, 3, 4, null, 5, 6);
select coalesce(null, 3, 1, 2, 3, 4, null, 5, 6);
-- assert_true(条件)  条件为true 返回null 条件为false 报错
select assert_true(1 == 2);

6 脱敏加密函数

在这里插入图片描述

-- mask 将大写字母转换为X 小写字母转换为x 数字转换为n
select mask("abc123XYZ");
-- 将大写字母转换为- 小写字母转换为* 数字转换$
select mask("abc123XYZ",'-','*','$'); -- 自定义替换的字母

--对前n个进行脱敏 mask_first_n(String str, int n);
select mask_first_n("abc123XYZ",2);
--对后n个进行脱敏 mask_last_n(String str, int n);
select mask_last_n("abc123XYZ",4);
-- 除了前n个 其余脱敏处理
select mask_show_first_n("abc123XYZ",2);
-- 除了后n个 其余脱敏处理
select mask_show_last_n("abc123XYZ",4);
-- 返回基于str的哈希 非字符串 返回Null;
select mask_hash("abc");
-- 获取哈希值
select hash("abc");

--SHA-1加密
select sha1("abc");
--SHA-2家族算法加密 sha2(string/binary,int)(SHA-224,SHA-256,SHA-384,SHA-512)
select sha2("abc",256);
select sha2("abc",512);
--crc32加密
select crc32("abc");
--md5加密
select md5("abc");

7 调用Java函数

-- hive调用java方法
select java_method("java.lang.Math","max",100,200);
-- 反射调用
select reflect("java.lang.Math","min",100,200);

函数高级

1 行转列

这里的行转列,指的是多行转一列.输入多行输出一行

在这里插入图片描述
涉及的函数

concat函数  字符串拼接,不可指定分隔符 
语法 
    concat(element1,element2,element3...)
举例 
	select concat('I','Love','Hive');
特点 如果任意一个元素为null,结果为null
	select concat('I','Love','Hive',null);
	
concat_ws函数 字符串拼接,可以指定分隔符
语法 
	concat_ws(splitChar,e1,e2,e3....|array<String>);
举例
	select concat_ws('-','I','Love','Hive');
	select concat_ws('-',`array`('aa','bb','cc','dd'));
特点 任意一个元素不为null,结果就不为null
	select concat_ws('-','I','Love','Hive',null);
	
collect_list函数 用于将一列中的多行合并为一行 不进行去重
语法 
	collect_list(colName)
举例 
	select collect_list(price) from t_product;
	
collect_set函数 用于将一列中的多行合并为一行 去重
语法 
	 collect_set(colName)
举例
	select collect_list(price) from t_product;

还有聚合函数 count,sum,max,avg等等

准备数据

vi emp.tsv
name gender job
柳岩	女	班主任
唐嫣	女	讲师
金莲	女	班主任
大郎	男	讲师
小庆	男	讲师
武松	男	班主任
-- 获取如下结果,班主任    柳岩|金莲
女,讲师	 唐嫣
男,班主任	武松
男,讲师	 大郎|小庆

create table t_emp
(
    name   string,
    gender string,
    job    string
) row format delimited fields terminated by "\t";

load data local inpath '/root/emp.tsv' into table t_emp;

查询

在这里插入图片描述

-- 将gender和job合并为一列
select concat_ws(',', gender, job) as gender_job, name
from t_emp;

-- 得出结果
with t1 as (select concat_ws(',', gender, job) as gender_job, name
            from t_emp)
select t1.gender_job, concat_ws('|', collect_list(name))
from t1
group by t1.gender_job;

求每种工作每种性别各有多少人,分别有谁,获取如下结果

在这里插入图片描述

select job,
       count(*)                                    as total,
       sum(case gender when '男' then 1 else 0 end) as man,
       sum(case gender when '女' then 1 else 0 end) as woman,
       concat_ws('|', collect_list(name))          as names
from t_emp
group by job;

2 列传行

这里的列转行指的是将一行数据转换成多行,输入一行输出多行
在这里插入图片描述

涉及的函数

expload函数 用于将一个集合或者数组中的每个元素展开,将每个元素变为一行
语法 
    exploade(Map|Array)
举例 
	select explode(`array`(1,2,3,4,5));
	select explode(split('a,b,c,d',','));
	select explode(`map`('liuyan','38','tangyan','18'));

建表准备数据

 name		category
《八佰》	战争,动作,爱国,剧情
《当幸福来敲门》	剧情,励志,怀旧,心理,故事
《悬崖之上》	战争,爱国,抗日,谍战

create table t_movie
(
    name     string,
    category string
) row format delimited fields terminated by "\t";

load data local inpath '/root/movie.txt' overwrite into table t_movie;

select * from t_movie;

查询

在这里插入图片描述

-- 先来炸裂所有分类
select explode(split(category, ',')) from t_movie;

-- 但是当我们加上name时 查询时 报错
-- UDTF's are not supported outside the SELECT clause, nor nested in expressions
select name, explode(split(category, ',')) from t_movie; -- 报错

我们发现在select条件中,如果只有explode函数表达式,程序执行是没有任何问题的.但是如果在select条件中,包含explode和其他字段,就会报错. 那么如何理解这个错误?为什么在select的时候,explode的旁边不支持其他字段的同时出现?

UDTF语法限制

  • explode函数属于UDTF表生成函数,explode执行返回的结果可以理解为一张虚拟的表,其数据来源于源表;
  • 在select中只查询源表数据没有问题,只查询explode生成的虚拟表数据也没问题,但是不能在只查询源表的时候,既想返回源表字段又想返回explode生成的虚拟表字段;通俗点讲,有两张表,不能只查询一张表但是又想返回分别属于两张表的字段;

在这里插入图片描述

如何解决?

1.从SQL层面上来说上述问题的解决方案是:对两张表进行join关联查询

2.Hive专门提供了语法lateral View侧视图,专门用于搭配explode这样的UDTF函数,以满足上述需要.

-- laterval view相当于自带关联条件 t_moive和t1进行 join连接
select name, t1.categroy from t_movie lateral view explode(split(category,',')) t1 as categroy;

在这里插入图片描述

-- 向表中添加一个没有分类的电影  category为null
vi moive2.txt
<战狼> 
load data local inpath '/root/movie2.txt'  into table t_movie;

select  * from t_movie;

-- 查询时 发现战狼电影不显示
select name, t1.categroy
from t_movie lateral view explode(split(category, ',')) t1 as categroy;

-- 如果想显示 需要写 laterval view outer  使用outer 显示null值
select name, t1.categroy
from t_movie lateral view outer explode(split(category, ',')) t1 as categroy;

3 聚合增强

增强聚合的grouping_sets、cube、rollup这几个函数主要适用于OLAP多维数据分析模式中,多维分析中的指的分析问题时看待问题的维度、角度。

下面我们来准备一下数据,通过案例更好的理解函数的功能含义.

2018-03,2018-03-10,cookie1
2018-03,2018-03-10,cookie5
2018-03,2018-03-12,cookie7
2018-04,2018-04-12,cookie3
2018-04,2018-04-13,cookie2
2018-04,2018-04-13,cookie4
2018-04,2018-04-16,cookie4
2018-03,2018-03-10,cookie2
2018-03,2018-03-10,cookie3
2018-04,2018-04-12,cookie5
2018-04,2018-04-13,cookie6
2018-04,2018-04-15,cookie3
2018-04,2018-04-15,cookie2
2018-04,2018-04-16,cookie1
--表创建并且加载数据
CREATE TABLE cookie_info
(
    month    STRING,
    day      STRING,
    cookieid STRING
) ROW FORMAT DELIMITED
    FIELDS TERMINATED BY ',';

load data local inpath '/root/cookie.txt' into table cookie_info;

select *
from cookie_info;
3.1 grouping_sets

grouping sets是一种将多个group by逻辑写在一个sql语句中的便利写法。等价于将不同维度的GROUP BY结果集进行UNION ALL。GROUPING__ID表示结果属于哪一个分组集合。

SELECT
    month,
    day,
    COUNT(DISTINCT cookieid) AS nums,
    GROUPING__ID
FROM cookie_info
GROUP BY month,day
    GROUPING SETS (month,day) --这里是关键
ORDER BY GROUPING__ID;

--等价于
SELECT month, NULL, COUNT(DISTINCT cookieid) AS nums, 1 AS GROUPING__ID
FROM cookie_info
GROUP BY month
UNION ALL
SELECT NULL as month, day, COUNT(DISTINCT cookieid) AS nums, 2 AS GROUPING__ID
FROM cookie_info
GROUP BY day;
--再比如
SELECT month,
       day,
       COUNT(DISTINCT cookieid) AS nums,
       GROUPING__ID
FROM cookie_info
GROUP BY month, day
    GROUPING SETS ( month, day, ( month, day)) --1 month   2 day    3 (month,day)
ORDER BY GROUPING__ID;

--等价于
SELECT month, NULL, COUNT(DISTINCT cookieid) AS nums, 0 AS GROUPING__ID
FROM cookie_info
GROUP BY month
UNION ALL
SELECT NULL, day, COUNT(DISTINCT cookieid) AS nums, 1 AS GROUPING__ID
FROM cookie_info
GROUP BY day
UNION ALL
SELECT month, day, COUNT(DISTINCT cookieid) AS nums, 2 AS GROUPING__ID
FROM cookie_info
GROUP BY month, day;
3.2 cube

cube表示根据GROUP BY的维度的所有组合进行聚合。

对于cube来说,如果有n个维度,则所有组合的总个数是:2^n

比如cube有a,b,c 3个维度,则所有组合情况是: (a,b,c),(a,b),(b,c),(a,c),(a),(b),©,()

SELECT
    month,
    day,
    COUNT(DISTINCT cookieid) AS nums,
    GROUPING__ID
FROM cookie_info
GROUP BY month,day
WITH CUBE
ORDER BY GROUPING__ID;

--等价于
SELECT NULL, NULL, COUNT(DISTINCT cookieid) AS nums, 0 AS GROUPING__ID
FROM cookie_info
UNION ALL
SELECT month, NULL, COUNT(DISTINCT cookieid) AS nums, 1 AS GROUPING__ID
FROM cookie_info
GROUP BY month
UNION ALL
SELECT NULL, day, COUNT(DISTINCT cookieid) AS nums, 2 AS GROUPING__ID
FROM cookie_info
GROUP BY day
UNION ALL
SELECT month, day, COUNT(DISTINCT cookieid) AS nums, 3 AS GROUPING__ID
FROM cookie_info
GROUP BY month, day;
3.3 rollup

rollup是cube的子集,以最左侧的维度为主,从该维度进行层级聚合。

比如ROLLUP有a,b,c3个维度,则所有组合情况是:(a,b,c),(a,b),(a),()

-- month和day
SELECT month,
       day,
       COUNT(DISTINCT cookieid) AS nums,
       GROUPING__ID
FROM cookie_info
GROUP BY month, day
WITH ROLLUP
ORDER BY GROUPING__ID;
-- 等价于  所有,month,month day
SELECT NULL, NULL, COUNT(DISTINCT cookieid) AS nums, 0 AS GROUPING__ID
FROM cookie_info
UNION ALL
SELECT month, NULL, COUNT(DISTINCT cookieid) AS nums, 1 AS GROUPING__ID
FROM cookie_info
GROUP BY month
UNION ALL
SELECT month, day, COUNT(DISTINCT cookieid) AS nums, 3 AS GROUPING__ID
FROM cookie_info
GROUP BY month, day;
-- day 和month
SELECT month,
       day,
       COUNT(DISTINCT cookieid) AS nums,
       GROUPING__ID
FROM cookie_info
GROUP BY day, month
WITH ROLLUP
ORDER BY GROUPING__ID;

-- 等价于  所有 ,day,day month
SELECT NULL, NULL, COUNT(DISTINCT cookieid) AS nums, 0 AS GROUPING__ID
FROM cookie_info
UNION ALL
SELECT null, day, COUNT(DISTINCT cookieid) AS nums, 1 AS GROUPING__ID
FROM cookie_info
GROUP BY day
UNION ALL
SELECT month, day, COUNT(DISTINCT cookieid) AS nums, 3 AS GROUPING__ID
FROM cookie_info
GROUP BY day, month;

4 窗口函数

窗口函数(Window functions )也叫做开窗函数、OLAP函数,其最大特点是∶输入值是从SELECT语句的结果集中的一行或多行的“窗口”中获取的。
窗口函数可以简单地解释为类似于聚合函数的计算函数,但是通过GROUP BY子句组合的常规聚合会隐藏正在聚合的各个行,最终输出一行,窗口函数聚合后还可以访问当中的各个行,并且可以将这些行中的某些属性添加到结果集中。

在这里插入图片描述

select * from stu_mark;
-- 常规分组查询 求分数和
select sname,sum(score) from stu_mark group by  sname;

在这里插入图片描述

-- 窗口函数分组
select sname,subject,score,sum(score) over (partition by sname) as total_score  from stu_mark;

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值