0%

函数

hive函数全解析:从内置函数到自定义函数的实战指南

Hive 提供了丰富的函数库,包括内置函数(UDF、UDAF、UDTF)和自定义函数,满足数据清洗、转换、聚合等复杂分析需求。本文详细讲解 Hive 函数的分类、常用内置函数(尤其是窗口函数)的用法,以及自定义函数的开发流程,帮助开发者高效处理数据。

Hive 函数基础与分类

Hive 函数按输入输出关系可分为三类,覆盖不同的数据处理场景:

函数分类

类型 全称 作用 示例
UDF User-Defined Function 一进一出(单条记录输入,单条结果输出) concat()nvl()
UDAF User-Defined Aggregate Function 多进一出(多条记录输入,单条聚合结果输出) sum()avg()collect_set()
UDTF User-Defined Table-Generating Function 一进多出(单条记录输入,多条结果输出) explode()split()

函数查询与帮助

  • 查看所有内置函数

    1
    hive> show functions;  -- 列出所有可用函数  
  • 查看函数用法

    1
    2
    3
    4
    -- 基础说明  
    hive> desc function concat;
    -- 详细说明(含示例)
    hive> desc function extended concat;
  • 模糊查询函数

    1
    hive> desc function like '*date*';  -- 查找含“date”的函数  

常用内置函数详解

数据清洗与转换函数

空值处理:nvl

NULL 值赋默认值,避免计算异常。

1
2
3
4
nvl(value, default_value)  -- 若 value 为 NULL,返回 default_value,否则返回 value  

-- 示例:将 NULL 薪资替换为 0
select ename, nvl(sal, 0) from emp;
字符串拼接:concatconcat_ws
  • concat:拼接多个字符串,任意参数为 NULL 则返回 NULL

    1
    2
    3
    4
    concat(str1, str2, ...)  

    -- 示例:拼接姓名和部门
    select concat(ename, '_', deptno) from emp; -- 输出:'张三_10'
  • concat_ws:指定分隔符拼接字符串,支持数组输入,忽略 NULL

    1
    2
    3
    4
    concat_ws(separator, str1, str2, ...)  -- separator 为分隔符  

    -- 示例:用逗号拼接姓名、部门、薪资
    select concat_ws(',', ename, deptno, sal) from emp; -- 输出:'张三,10,5000'
字符串切割与展开:splitexplode
  • split:按正则表达式切割字符串为数组(UDTF 输入)。

    1
    2
    3
    4
    split(str, regex)  -- 按 regex 切割 str,返回数组  

    -- 示例:切割逗号分隔的标签
    select split('java,python,sql', ',') as tags from dual; -- 输出:["java","python","sql"]
  • explode:将数组或 Map 拆分为多行(UDTF 输出)。

    1
    2
    3
    4
    5
    6
    7
    8
    explode(array)  -- 将数组元素拆分为多行  

    -- 示例:展开标签数组
    select explode(split('java,python,sql', ',')) as tag from dual;
    -- 输出:
    java
    python
    sql
侧视图:lateral view

explode 结合,解决 UDTF 不能直接与其他列共存的问题(UDTF 需单独使用)。

1
2
3
4
5
6
lateral view UDTF(expression) 别名 as 列名  

-- 示例:将订单表的商品 ID 数组拆分为多行,并关联订单 ID
select order_id, product_id
from orders
lateral view explode(product_ids) temp as product_id; -- temp 为临时表别名

日期与时间函数

Hive 日期函数支持时间戳、字符串格式转换,满足时序分析需求。

日期格式化:date_format

将日期字符串转换为指定格式(仅支持 yyyy-MM-ddyyyy-MM-dd HH:mm:ss 等标准格式)。

1
2
3
4
date_format(date_str, format)  

-- 示例:将日期转为 yyyyMMdd 格式
select date_format('2023-10-01', 'yyyyMMdd'); -- 输出:20231001
时间戳转换:from_unixtimeunix_timestamp
  • from_unixtime:将 Unix 时间戳(秒级)转为日期字符串。

    1
    2
    3
    4
    from_unixtime(timestamp, format)  

    -- 示例:时间戳转日期
    select from_unixtime(1696108800, 'yyyy-MM-dd'); -- 输出:2023-10-01(对应时间戳的日期)
  • unix_timestamp:将日期字符串转为 Unix 时间戳(支持自定义格式)。

    1
    2
    3
    4
    unix_timestamp(date_str, format)  -- 若不指定 format,默认解析 'yyyy-MM-dd HH:mm:ss'  

    -- 示例:自定义格式字符串转时间戳
    select unix_timestamp('2023/10/01', 'yyyy/MM/dd'); -- 输出:1696108800
跨格式日期转换:from_unixtime + unix_timestamp

结合两者实现非标准格式日期的转换(如 yyyy/MM/ddyyyyMMdd)。

1
2
3
4
5
-- 示例:将 '2023/10/01' 转为 '20231001'  
select from_unixtime(
unix_timestamp('2023/10/01', 'yyyy/MM/dd'), -- 先转时间戳
'yyyyMMdd' -- 再转目标格式
);

聚合函数:collect_setsum

  • collect_set:聚合列值为去重数组(UDAF),常用于多值合并。

    1
    2
    3
    4
    5
    collect_set(col)  -- 返回无重复元素的数组  

    -- 示例:聚合每个部门的员工姓名
    select deptno, collect_set(ename) from emp group by deptno;
    -- 输出:10 ["张三","李四"]
  • sum/avg/count:基础聚合函数,与 group by 配合使用。

    1
    2
    -- 示例:计算每个部门的平均薪资  
    select deptno, avg(sal) as avg_sal from emp group by deptno;

窗口函数:over() 高级分析

窗口函数是 Hive 数据分析的核心工具,允许在保留原始数据的同时进行聚合计算,支持定义 “数据窗口”(分析范围)。

窗口函数基础语法
1
2
3
4
5
分析函数(列) OVER (  
[PARTITION BY 分区列] -- 按列分组,每组独立计算
[ORDER BY 排序列] -- 组内排序
[ROWS | RANGE BETWEEN 窗口范围] -- 定义窗口大小(如当前行前后 N 行)
)
无窗口限制:全局聚合

未指定 PARTITION BYORDER BY 时,窗口为整个数据集。

1
2
3
4
5
-- 示例:计算所有员工的总薪资,保留每行原始数据  
select ename, sal, sum(sal) over() as total_sal from emp;
-- 输出:
-- 张三 5000 20000
-- 李四 6000 20000
按列分区:PARTITION BY

按指定列分组,组内独立计算窗口(类似 group by 但保留明细)。

1
2
3
4
5
6
7
-- 示例:按部门分区,计算每个部门的总薪资  
select ename, deptno, sal,
sum(sal) over(partition by deptno) as dept_total -- 按 deptno 分组
from emp;
-- 输出:
-- 张三 10 5000 11000 (部门 10 总薪资)
-- 李四 10 6000 11000
定义窗口范围:ROWS BETWEEN

通过 ROWSRANGE 限制窗口内的行数(如 “当前行及前 2 行”)。

范围关键字 含义
CURRENT ROW 当前行
n PRECEDING 往前 n 行
n FOLLOWING 往后 n 行
UNBOUNDED PRECEDING 从分组第一行开始
UNBOUNDED FOLLOWING 到分组最后一行结束

示例:计算累计薪资

1
2
3
4
5
6
7
8
9
10
-- 按薪资升序,计算从第一行到当前行的累计薪资  
select ename, sal,
sum(sal) over(
order by sal
rows between unbounded preceding and current row -- 窗口:从起点到当前行
) as cum_sal
from emp;
-- 输出:
-- 王五 3000 3000
-- 张三 5000 8000 (3000+5000)
排序与排名函数:rank/dense_rank/row_number

用于组内排序,返回每行的排名序号,差异如下:

函数 特点 示例(薪资排序)
rank() 相同值排名相同,后续排名跳过 1, 2, 2, 4
dense_rank() 相同值排名相同,后续排名连续 1, 2, 2, 3
row_number() 相同值排名不同,按顺序递增 1, 2, 3, 4

示例:部门内薪资排名

1
2
3
4
5
select ename, deptno, sal,  
rank() over(partition by deptno order by sal desc) as rk,
dense_rank() over(partition by deptno order by sal desc) as drk,
row_number() over(partition by deptno order by sal desc) as rnum
from emp;

自定义函数开发:UDF 实战

当内置函数无法满足需求时,可开发自定义函数(UDF)。以下以 “小写转大写” UDF 为例,讲解开发流程。

开发环境准备

依赖配置(Maven pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<dependencies>  
<!-- Hadoop 依赖 -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.6.0</version>
</dependency>
<!-- Hive 依赖 -->
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>1.2.1</version>
</dependency>
</dependencies>
UDF 实现类

继承 org.apache.hadoop.hive.ql.exec.UDF,重写 evaluate 方法(核心逻辑)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import org.apache.hadoop.hive.ql.exec.UDF;  
import org.apache.commons.lang.StringUtils;

public class UpperCaseUDF extends UDF {
// 输入字符串,输出大写字符串
public String evaluate(String input) {
if (StringUtils.isEmpty(input)) {
return null; // 处理空值
}
return input.toUpperCase(); // 核心逻辑:转大写
}

// 本地测试
public static void main(String[] args) {
System.out.println(new UpperCaseUDF().evaluate("hello")); // 输出:HELLO
}
}

打包与部署

打包

用 Maven 打包为 JAR 文件(如 hive-udf-demo.jar)。

临时函数注册(当前会话有效)
  1. 上传 JAR 到 Hive 客户端所在机器;

  2. 在 Hive 中添加 JAR 并注册函数:

1
2
3
4
5
-- 添加 JAR  
hive> add jar /path/to/hive-udf-demo.jar;

-- 注册临时函数(函数名:upper_udf,关联类全路径)
hive> create temporary function upper_udf as 'com.example.UpperCaseUDF';
永久函数注册(全局有效)
  1. 将 JAR 上传到 HDFS 路径(如 /user/hive/udf/);

  2. 注册永久函数:

    1
    2
    hive> create function upper_udf as 'com.example.UpperCaseUDF'  
    using jar 'hdfs:///user/hive/udf/hive-udf-demo.jar';

使用自定义函数

1
hive> select upper_udf('hello hive');  -- 输出:HELLO HIVE  

函数使用注意事项

  1. 空值处理:多数函数对 NULL 敏感(如 concatNULL 返回 NULL),需用 nvl 提前处理。
  2. 性能优化
    • 避免在 where 中使用复杂函数(如 date_format),可提前预处理;
    • 窗口函数数据量大时,合理设置 PARTITION BY 减少窗口大小。
  3. 自定义函数限制
    • UDF 仅支持单条记录处理,复杂聚合需用 UDAF;
    • 永久函数需确保 HDFS JAR 路径对所有节点可见。

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10