HIVE作为数据仓库处理常用工具,如同RDBMS关系型数据库中标准SQL语法一样,Hive SQL也内置了不少系统函数,满足于用户在不同场景下的数据分析需求,以提高开发SQL数据分析的效率。
我们可以使用show functions查看当下版本支持的函数,并且可以通过describe function extended funcname来查看函数对应的使用方式和方法,下面我们将描述HIVE SQL中常用函数的高阶使用场景。
如下活动列表:tb_activities
活动ID | 活动名称列表 |
---|---|
1 | 双111,国庆,元旦 |
2 | 黄金周,国庆,元旦 |
希望转换为列类型活动表:tb_activitity
活动ID | 活动名称 |
---|---|
1 | 双11 |
1 | 国庆 |
1 | 元旦 |
2 | 黄金周 |
2 | 国庆 |
2 | 元旦 |
使用到Hive内置一个非常著名的UDTF函数,名字叫做explode函数,中文戏称为“爆炸函数”,可以炸开数据转换为多行。
insert into table tb_activitity select id,activity from tb_activities
lateral view explode(split(activities,','))enum_tmp as activity;
如上1所示,希望从tb_activity转换为tb_activities,通过collect_set()方法和group by id 将列转换为行,实现如下:
select id, concat_ws(',',collect_set(activity)) as activities
from tb_activity group by id;
可以通过rank() 方法的使用,实现对指定列进行排名,输出排名结果。例如商品总数表:t_item_sum,需要实现排名功能:
item_id | item_sum |
---|---|
1001 | 20 |
1002 | 12 |
1003 | 62 |
1004 | 15 |
期望得到:
item_id | item_sum | rank |
---|---|---|
1003 | 62 | 1 |
1001 | 20 | 2 |
1004 | 15 | 3 |
1002 | 12 | 4 |
代码实现如下:
select item_id,item_sum,rank()over(order by item_sum desc) as rank from t_item_sum;
在查询数据时如果有重复,我们可以使用用distinct 去除重复值,但使用 distinct 只能去除所有查询列都相同的记录,如果某个字段不同,distinct 就无法去重
。这时我们可以用 row_number()over(partitioon by column1 order by column2) 先进行分组。
例如:有活动表数据列“活动id,用户id,活动名称,客户群组,过期时间”,希望按照”活动id,活动名称,客户群组”去重,取最新一条数据。
id | user_id | activity | cust_group | expired_at |
---|---|---|---|---|
BCP015 | 1001 | 春节活动A | 高价值 | 2023-10-05 |
BCP015 | 1001 | 春节活动A | 高价值 | 2023-10-15 |
BCP015 | 1001 | 春节活动A | 高价值 | 2023-10-28 |
BCP025 | 1002 | 春节活动B | 中价值 | 2023-10-05 |
BCP025 | 1002 | 春节活动B | 中价值 | 2023-10-25 |
BCP030 | 1003 | 春节活动C | 中价值 | 2023-10-25 |
期望得到:
id | user_id | activity | cust_group | expired_at |
---|---|---|---|---|
BCP015 | 1001 | 春节活动A | 高价值 | 2023-10-28 |
BCP025 | 1002 | 春节活动B | 中价值 | 2023-10-25 |
BCP030 | 1003 | 春节活动C | 中价值 | 2023-10-25 |
使用row_number()over(partitioon by) 分组去重。
select tt1.* from(select id, user_id, activity,cust_group,
row_number() over(partition by concat(id,activity,cust_group)
order by expired_at desc)as row_num
from tb_acitivity_full)tt1 where tt1.row_num=1;
GROUPING SETS,GROUPING__ID,CUBE,ROLLUP,这几个hive分析函数通常用于OLAP中,不能累加,而且需要根据不同维度上钻( roll up )和下钻( drill down )的指标统计
,比如,分小时、天、月的UV数。上钻是沿着维度的层次向上聚集汇总数据,下钻是在分析时加深维度,对数据进行层层深入的查看。通过逐层下钻,数据更加一目了然,更能充分挖掘数据背后的价值,及时做出更加正确的决策。
OLAP函数 | 使用说明 |
---|---|
GROUPING SETS | 根据不同的维度组合进行聚合,等价于将不同维度的GROUP BY结果集进行UNION ALL |
GROUPING__ID | 表示结果属于哪一个分组集合,属于虚字段 |
CUBE | 可根据GROUP BY的维度的所有组合进行聚合 |
ROLLUP | 作为CUBE的子集,以最左侧的维度为主,从该维度进行层级聚合 |
如4所示,希望对指标值进行统计,期望结果:
indicator | enum_value | count |
---|---|---|
id | BCP015 | 3 |
id | BCP025 | 2 |
id | BCP030 | 1 |
activity | 春节活动A | 3 |
activity | 春节活动B | 2 |
activity | 春节活动C | 1 |
cust_group | 高价值 | 3 |
cust_group | 中价值 | 3 |
通过grouping__id 内层SQL处理结果,表2:
groupId | id | activity | cust_group | uv |
---|---|---|---|---|
1728 | id_BCP015 | NULL | NULL | 3 |
1724 | id_BCP025 | NULL | NULL | 2 |
1723 | id_BCP030 | NULL | NULL | 1 |
2728 | NULL | activity_春节活动A | NULL 3 | |
2724 | NULL | activity_春节活动B | NULL 2 | |
2723 | NULL | activity_春节活动C | NULL 1 | |
3723 | NULL | NULL | cust_group_高价值 | 3 |
3724 | NULL | NULL | cust_group_中价值 | 3 |
select
split(coalesce(
id,
activity,
cust_group),'\\_')[0] as indicator,
coalesce(
split(id, '\\_')[1],
split(activity, '\\_')[1],
split(cust_group, '\\_')[1],
) as enum_value
sum(uv) as count
from (
-- 内层SQL处理结果,对应上表2
select grouping__id as groupId,
concat('id|',id) as id,
concat('activity|', activity) as activity,
concat('cust_group|',cust_group) as cust_group,
count(*) as uv
from tb_acitivity_full
group by
concat('id|',id),
concat('activity|', activity),
concat('cust_group|',cust_group)
grouping sets(
concat('id|',id),
concat('activity|', activity),
concat('cust_group|',cust_group)
)as tt1
group by split(coalesce(
id,
activity,
cust_group),'\\_')[0],
coalesce(
split(id, '\\_')[1],
split(activity, '\\_')[1],
split(cust_group, '\\_')[1],
);
JSON数据作为数据存储和数据处理中最常见的结构化数据格式之一,许多场景下都会将数据以JSON格式存储在文件系统(HDFS/MINIO等)中,当构建数据仓库时,对JSON格式的数据进行处理和分析,就需要在Hive中使用对应函数对JSON格式的数据进行解析读取。
例如,JSON格式的数据如下:
商品ID | 商品名称 | 额外信息 |
---|---|---|
1001 | IP15 | “fixedIntegral”:200, “source”:“wechat”,“stages”:12} |
获取商品可使用的固定积分:
select get_json_object(extra_json, '$fixedIntegral) as integral
from t_items;
select translate('abcdef', 'adc', '19') tb_translate_exe
输出:
1b9ef
正则替换
SELECT aa
,REGEXP_REPLACE(aa, '[a-z]', '') -- 替换所有字母
,REGEXP_REPLACE(aa, '[abc]', '') -- 替换指定字母
,REGEXP_REPLACE(aa, '[^abc]', '') -- 替换所有非字母
,REGEXP_REPLACE(aa, '[0-9]', '') -- 替换所有数字
,REGEXP_REPLACE(aa, '[\\s\\S]', '') -- 替换空白符、换行,\\s:是匹配所有空白符,包括换行,\\S:非空白符,不包括换行。
,REGEXP_REPLACE(aa, '\\w', '') -- 替换所有字母、数字、下划线。等价于 [A-Za-z0-9_]
,REGEXP_REPLACE(aa, '[-8+]', '') -- 只替换-8这个字符
,REGEXP_REPLACE(aa, '[-8*]', '') -- 替换-8、-、8这几个字符
FROM (
SELECT '5e40b2b8-0916-42c0-899a-eaf4b2df 5268' AS aa
UNION ALL
SELECT 'c81b5906-38d7-482c-8b66-be5d3359cbf6' AS aa
UNION ALL
SELECT '8856fd0a-2337-4605-963f-0d0d059b1937' AS aa
) t
;