函数

Hive 函数:内置函数够用 80% 的场景,窗口函数是分析利器,UDF 是最后一张牌

Hive 的函数分三类:

类型 输入 → 输出 典型函数
UDF 一行 → 一行 concatnvldate_format
UDAF 多行 → 一行 sumavgcollect_set
UDTF 一行 → 多行 explodesplit

日常开发中,80% 的需求用内置 UDF 和 UDAF 就能解决。窗口函数是进阶工具,解决”既要聚合又要保留明细”的问题。 自定义 UDF 是最后的手段——内置函数实在搞不定了再写

函数查询与帮助

  • 查看所有内置函数

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

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

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

数据清洗类函数

空值处理:nvl

-- 薪资为空时补 0
SELECT ename, nvl(sal, 0) FROM emp;

字符串拼接:concat / concat_ws

-- concat:直接拼,有一个 NULL 整个结果是 NULL
SELECT concat(ename, '_', deptno) FROM emp;

-- concat_ws:指定分隔符,自动跳过 NULL
SELECT concat_ws(',', ename, deptno, sal) FROM emp;

字符串切割:split

-- 把逗号分隔的标签切成数组
SELECT split('java,python,sql', ',') FROM dual;
-- 输出:["java","python","sql"]

数组展开:explode + lateral view

explode 把数组拆成多行,但必须跟 lateral view 配合使用:

-- 把每个标签拆成一行,同时保留订单 ID
SELECT order_id, tag
FROM orders
LATERAL VIEW explode(split(tags, ',')) t AS tag;

日期处理函数

函数 作用 示例
date_format 日期格式化 date_format('2026-07-01', 'yyyyMMdd')20260701
unix_timestamp 日期 → 时间戳 unix_timestamp('2026-07-01', 'yyyy-MM-dd')
from_unixtime 时间戳 → 日期 from_unixtime(1696108800, 'yyyy-MM-dd')

跨格式转换:先转时间戳,再转目标格式

-- 把 '2026/07/01' 转成 '20260701'
SELECT from_unixtime(
  unix_timestamp('2026/07/01', 'yyyy/MM/dd'),
  'yyyyMMdd'
);

聚合函数:多行 → 一行

函数 作用
sum 求和
avg 平均值
count 计数
max / min 最大 / 最小值
collect_set 去重合并成数组
collect_list 不去重合并成数组
-- 按部门汇总
SELECT deptno, 
       sum(sal) AS total_sal,
       avg(sal) AS avg_sal,
       collect_set(ename) AS employees
FROM emp
GROUP BY deptno;

窗口函数:聚合 + 保留明细

窗口函数是 Hive 最强大的分析工具。它的核心价值是:在保留每一行原始数据的同时,做聚合计算。

普通聚合 vs 窗口函数:

-- 普通聚合:结果只显示一行(部门汇总)
SELECT deptno, sum(sal) FROM emp GROUP BY deptno;
-- 输出:10    11000

-- 窗口函数:每一行都保留,同时显示部门汇总
SELECT ename, deptno, sal,
       sum(sal) OVER(PARTITION BY deptno) AS dept_total
FROM emp;
-- 输出:
-- 张三   10    5000    11000
-- 李四   10    6000    11000
-- 王五   20    3000    3000

窗口函数的基本结构:

函数() OVER (
  PARTITION BY 分组列   -- 可选,不写就是全表
  ORDER BY 排序列       -- 可选
  ROWS BETWEEN ...      -- 可选,定义窗口范围
)

常用窗口函数:

函数 作用
sum() OVER() 累计求和
avg() OVER() 移动平均
rank() OVER() 排名(有间隔)
dense_rank() OVER() 排名(无间隔)
row_number() OVER() 行号
lag(列, n) 取前 n 行的值
lead(列, n) 取后 n 行的值

场景1:按部门排名

SELECT ename, deptno, sal,
       rank() OVER(PARTITION BY deptno ORDER BY sal DESC) AS rnk
FROM emp;

rank vs dense_rank vs row_number:

函数 相同值行为
rank() 1, 2, 2, 4(跳过)
dense_rank() 1, 2, 2, 3(连续)
row_number() 1, 2, 3, 4(不重复)

场景2:累计求和

-- 按薪资升序,计算累计总和
SELECT ename, sal,
       sum(sal) OVER(ORDER BY sal
                     ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cum_sal
FROM emp;

场景3:同比/环比(取上一条数据)

-- 取上一个月的销售额
SELECT month, sales,
       lag(sales, 1) OVER(ORDER BY month) AS prev_month_sales
FROM sales_table;

自定义函数 UDF:内置不够用的时候再写

三步走:

1. 写 Java 类,继承 UDF,重写 evaluate

import org.apache.hadoop.hive.ql.exec.UDF;

public class UpperCaseUDF extends UDF {
    public String evaluate(String input) {
        if (input == null) return null;
        return input.toUpperCase();
    }
}

2. 打包成 JAR,上传

# 上传到 HDFS
hdfs dfs -put hive-udf.jar /user/hive/udf/

3. 在 Hive 里注册

-- 临时函数(当前会话有效)
ADD JAR /path/to/hive-udf.jar;
CREATE TEMPORARY FUNCTION upper_udf AS 'com.example.UpperCaseUDF';

-- 永久函数(全局有效)
CREATE FUNCTION upper_udf AS 'com.example.UpperCaseUDF'
USING JAR 'hdfs:///user/hive/udf/hive-udf.jar';

4. 使用

SELECT upper_udf('hello') FROM dual;  -- HELLO