Hive SQL 函数高阶应用场景

HIVE作为数据仓库处理常用工具,如同RDBMS关系型数据库中标准SQL语法一样,Hive SQL也内置了不少系统函数,满足于用户在不同场景下的数据分析需求,以提高开发SQL数据分析的效率。

我们可以使用show functions查看当下版本支持的函数,并且可以通过describe function extended funcname来查看函数对应的使用方式和方法,下面我们将描述HIVE SQL中常用函数的高阶使用场景。

1、行转列(explode)

如下活动列表:tb_activities

活动ID 活动名称列表
1 双111,国庆,元旦
2 黄金周,国庆,元旦

希望转换为列类型活动表:tb_activitity

活动ID 活动名称
1 双11
1 国庆
1 元旦
2 黄金周
2 国庆
2 元旦

使用到Hive内置一个非常著名的UDTF函数,名字叫做explode函数,中文戏称为"爆炸函数",可以炸开数据转换为多行。

sql 复制代码
insert into table tb_activitity select id,activity from tb_activities 
lateral view explode(split(activities,','))enum_tmp as activity;

2、列转行

如上1所示,希望从tb_activity转换为tb_activities,通过collect_set()方法和group by id 将列转换为行,实现如下:

sql 复制代码
 select id, concat_ws(',',collect_set(activity)) as activities 
 from tb_activity group by id;

3、排名(rank())

可以通过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

代码实现如下:

sql 复制代码
select item_id,item_sum,rank()over(order by item_sum desc) as rank from t_item_sum;

4、分组去重

在查询数据时如果有重复,我们可以使用用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) 分组去重。

sql 复制代码
  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;

5、指标统计

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
sql 复制代码
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],
  );

6、JSON数据处理

JSON数据作为数据存储和数据处理中最常见的结构化数据格式之一,许多场景下都会将数据以JSON格式存储在文件系统(HDFS/MINIO等)中,当构建数据仓库时,对JSON格式的数据进行处理和分析,就需要在Hive中使用对应函数对JSON格式的数据进行解析读取。

例如,JSON格式的数据如下:

商品ID 商品名称 额外信息
1001 IP15 "fixedIntegral":200, "source":"wechat","stages":12}

获取商品可使用的固定积分:

sql 复制代码
select get_json_object(extra_json, '$fixedIntegral) as integral
from t_items;

7、替换

7.1 translate 函数用法
sql 复制代码
select translate('abcdef', 'adc', '19') tb_translate_exe
输出:
1b9ef
  • translate(input,from,to)
  • input:输入字符串
  • from:需要匹配的字符
  • to :用哪些字符来替换被匹配到的字符
    注意点:这里from的字符与to字符在位置上存在一 一对应关系,也就是from中每个位置上的字符用to中对应位置的字符替换。
7.1 regexp_replace 函数

正则替换

sql 复制代码
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
;
相关推荐
Li.CQ2 小时前
SQL学习笔记(二)
笔记·sql·学习
白衣衬衫 两袖清风4 小时前
SQL联查案例
数据库·sql
晨曦5432107 小时前
MySQL MOD()函数详解与Python对比
sql
甘露s8 小时前
MySQL深入之索引、存储引擎和SQL优化
数据库·sql·mysql
偶遇急雨洗心尘8 小时前
记录一次服务器迁移时,数据库版本不一致导致sql函数报错和系统redirect重定向丢失域名问题
运维·服务器·数据库·sql
Logic1019 小时前
《Mysql数据库应用》 第2版 郭文明 实验5 存储过程与函数的构建与使用核心操作与思路解析
数据库·sql·mysql·学习笔记·计算机网络技术·形考作业·国家开放大学
小二·9 小时前
MyBatis基础入门《十六》企业级插件实战:基于 MyBatis Interceptor 实现 SQL 审计、慢查询监控与数据脱敏
数据库·sql·mybatis
小二·9 小时前
MyBatis基础入门《十二》批量操作优化:高效插入/更新万级数据,告别慢 SQL!
数据库·sql·mybatis
百锦再10 小时前
国产数据库的平替亮点——关系型数据库架构适配
android·java·前端·数据库·sql·算法·数据库架构
IT枫斗者11 小时前
Netty的原理和springboot项目整合
java·spring boot·后端·sql·科技·mysql·spring