Hive 与 MySQL 常用函数差异对比及语法示例
Hive 和 MySQL 虽然都支持 SQL 标准,但各自的设计目标不同(Hive 用于批处理,MySQL 用于事务),导致许多函数在函数名、参数顺序、返回值上存在明显差异。以下从 7 个类别详细对比,并提供可直接运行的语法示例。
一、字符串函数
| 功能 |
MySQL 语法 |
Hive 语法 |
差异说明 |
| 字符串长度(字符数) |
CHAR_LENGTH(str) |
LENGTH(str) |
Hive 的 LENGTH 返回字符数,MySQL 的 LENGTH 返回字节数 |
| 字符串长度(字节数) |
LENGTH(str) |
无直接函数 |
Hive 需用 OCTET_LENGTH(str) |
| 截取子串 |
SUBSTRING(str, pos, len) (pos 从1开始) |
SUBSTR(str, pos, len) 或 SUBSTRING |
功能相同,Hive 常用 SUBSTR |
| 查找子串位置 |
INSTR(str, substr) |
INSTR(str, substr) |
两者都支持,Hive 还支持 LOCATE |
| 正则提取 |
REGEXP_SUBSTR(str, pattern) |
regexp_extract(str, pattern, idx) |
Hive 必须指定捕获组索引 |
| 正则匹配 |
str REGEXP pattern 或 RLIKE |
str RLIKE pattern 或 REGEXP |
两者都支持 RLIKE |
| 字符串分割 |
SUBSTRING_INDEX(str, delim, count) |
SPLIT(str, delim) 返回数组 |
Hive 返回 array 类型,需配合 [index] 或 explode |
| 分组拼接 |
GROUP_CONCAT(col ORDER BY col SEPARATOR ',') |
COLLECT_LIST(col) + CONCAT_WS |
Hive 需两步:先收集成数组,再连接 |
示例
SELECT CHAR_LENGTH('Hello世界');
SELECT LENGTH('Hello世界');
SELECT REGEXP_SUBSTR('abc123def456', '[0-9]+');
SELECT dept, GROUP_CONCAT(name ORDER BY name SEPARATOR ',')
FROM emp GROUP BY dept;
SELECT LENGTH('Hello世界');
SELECT regexp_extract('abc123def456', '([0-9]+)', 1);
SELECT dept, CONCAT_WS(',', COLLECT_LIST(name))
FROM emp GROUP BY dept;
二、日期时间函数
| 功能 |
MySQL 语法 |
Hive 语法 |
差异说明 |
| 当前日期时间 |
NOW(), CURDATE(), CURTIME() |
CURRENT_TIMESTAMP(), CURRENT_DATE |
名称不同 |
| 日期加减(天) |
DATE_ADD(date, INTERVAL n DAY) |
DATE_ADD(date, n) |
Hive 参数更简单 |
| 日期加减(复杂单位) |
DATE_ADD(date, INTERVAL n MONTH) |
ADD_MONTHS(date, n) |
Hive 有专用函数 |
| 日期差(天数) |
DATEDIFF(date1, date2) |
DATEDIFF(date1, date2) |
相同(但 Hive 需保证格式) |
| 日期差(其他单位) |
TIMESTAMPDIFF(unit, start, end) |
无直接函数 |
Hive 用 unix_timestamp 计算秒再转换 |
| 提取年月日 |
YEAR(date), MONTH(date), DAY(date) |
相同 |
一致 |
| 格式化 |
DATE_FORMAT(date, '%Y-%m-%d') |
DATE_FORMAT(date, 'yyyy-MM-dd') |
格式字符串不同(MySQL 用 %,Hive 用 Java 格式) |
| 字符串转日期 |
STR_TO_DATE(str, '%Y-%m-%d') |
TO_DATE(str) 或 FROM_UNIXTIME |
Hive 自动识别常用格式 |
| 时间戳转日期 |
FROM_UNIXTIME(ts) |
FROM_UNIXTIME(ts) |
相同 |
| 日期转时间戳 |
UNIX_TIMESTAMP(date) |
UNIX_TIMESTAMP(date) |
相同 |
示例
SELECT CURDATE();
SELECT DATE_ADD('2024-01-31', INTERVAL 1 DAY);
SELECT TIMESTAMPDIFF(HOUR, '2024-01-01 08:00:00', '2024-01-01 20:00:00');
SELECT DATE_FORMAT('2024-01-01', '%Y年%m月%d日');
SELECT CURRENT_DATE;
SELECT DATE_ADD('2024-01-31', 1);
SELECT ADD_MONTHS('2024-01-31', 1);
SELECT (UNIX_TIMESTAMP('2024-01-01 20:00:00') - UNIX_TIMESTAMP('2024-01-01 08:00:00')) / 3600;
SELECT DATE_FORMAT('2024-01-01', 'yyyy年MM月dd日');
三、条件函数
| 功能 |
MySQL 语法 |
Hive 语法 |
差异说明 |
| 简单条件 |
IF(cond, true_val, false_val) |
相同 |
一致 |
| 多分支 |
CASE WHEN ... THEN ... END |
相同 |
一致 |
| 空值替换 |
IFNULL(expr, default) |
NVL(expr, default) |
函数名不同 |
| 多个空值替换 |
COALESCE(val1, val2, ...) |
相同 |
一致 |
| 判断空值 |
ISNULL(expr) |
无 |
Hive 直接用 expr IS NULL |
示例
SELECT IFNULL(NULL, 'default');
SELECT ISNULL(NULL);
SELECT NVL(NULL, 'default');
SELECT NULL IS NULL;
四、聚合函数
| 功能 |
MySQL 语法 |
Hive 语法 |
差异说明 |
| 基本聚合 |
COUNT, SUM, AVG, MAX, MIN |
相同 |
一致 |
| 去重计数 |
COUNT(DISTINCT col) |
相同(但大数据量下慢) |
Hive 可用 NDV 或 approx_count_distinct 近似去重 |
| 中位数 |
无 |
PERCENTILE(col, 0.5) |
Hive 支持精确中位数(整数列) |
| 近似分位数 |
无 |
PERCENTILE_APPROX(col, 0.5) |
Hive 支持近似分位数 |
| 分组拼接 |
GROUP_CONCAT |
COLLECT_LIST + CONCAT_WS |
见字符串部分 |
示例
SELECT COUNT(DISTINCT user_id) FROM orders;
SELECT AVG(score) FROM (
SELECT score, ROW_NUMBER() OVER (ORDER BY score) AS rn, COUNT(*) OVER () AS cnt
FROM scores
) t WHERE rn IN (FLOOR((cnt+1)/2), CEIL((cnt+1)/2));
SELECT NDV(user_id) FROM orders;
SELECT approx_count_distinct(user_id) FROM orders;
SELECT PERCENTILE(score, 0.5) FROM scores;
五、类型转换
| 功能 |
MySQL 语法 |
Hive 语法 |
差异说明 |
| 通用转换 |
CAST(expr AS type) |
相同 |
但类型名不同 |
| 类型名示例 |
SIGNED, UNSIGNED, CHAR |
INT, DOUBLE, STRING |
Hive 类型更接近 Java |
| 字符串转整数 |
CONVERT(expr, SIGNED) |
CAST(expr AS INT) |
MySQL 有 CONVERT,Hive 只用 CAST |
示例
SELECT CAST('123' AS SIGNED);
SELECT CONVERT('456', SIGNED);
SELECT CAST('123' AS INT);
SELECT CAST('123.45' AS DOUBLE);
六、表生成函数(UDTF)与行转列
Hive 支持 EXPLODE 等 UDTF,MySQL 不支持。
| 功能 |
Hive 语法 |
MySQL 替代方案 |
| 数组展开为多行 |
LATERAL VIEW EXPLODE(array) t AS elem |
使用递归 CTE 或写存储过程 |
| Map 展开 |
LATERAL VIEW EXPLODE(map) t AS key, value |
无法直接实现 |
| 列转行(多列转多行) |
LATERAL VIEW + 多个 EXPLODE |
使用 UNION ALL 硬编码 |
示例
SELECT word
FROM (SELECT 'a,b,c' AS str) t
LATERAL VIEW EXPLODE(SPLIT(str, ',')) tmp AS word;
WITH RECURSIVE split AS (
SELECT 1 AS pos, SUBSTRING_INDEX('a,b,c', ',', 1) AS word,
SUBSTRING('a,b,c', LENGTH(SUBSTRING_INDEX('a,b,c', ',', 1)) + 2) AS rest
UNION ALL
SELECT pos+1, SUBSTRING_INDEX(rest, ',', 1),
SUBSTRING(rest, LENGTH(SUBSTRING_INDEX(rest, ',', 1)) + 2)
FROM split WHERE rest != ''
)
SELECT word FROM split;
七、JSON 函数
| 功能 |
MySQL 5.7+ |
Hive |
差异说明 |
| 提取 JSON 值 |
JSON_EXTRACT(json, path) |
get_json_object(json, path) |
函数名不同,路径语法相似 |
| 提取多个字段 |
多次调用 JSON_EXTRACT |
json_tuple(json, col1, col2, ...) |
Hive 有专用多列提取 |
| 检查有效性 |
JSON_VALID(json) |
无 |
Hive 无法检查 |
示例
SELECT JSON_EXTRACT('{"name":"Alice","age":30}', '$.name');
SELECT JSON_UNQUOTE(JSON_EXTRACT('{"name":"Alice"}', '$.name'));
SELECT get_json_object('{"name":"Alice","age":30}', '$.name');
SELECT t.name, t.age
FROM (SELECT '{"name":"Alice","age":30}' AS json) a
LATERAL VIEW json_tuple(a.json, 'name', 'age') t AS name, age;
八、其他注意事项
| 项目 |
MySQL |
Hive |
说明 |
| 窗口函数 |
8.0+ 支持 |
0.11+ 支持 |
语法相同 |
| NULL 排序 |
默认 NULL 最小(升序在前) |
默认 NULL 最大(升序在后) |
Hive 可用 NULLS FIRST/LAST |
| 执行计划 |
EXPLAIN |
EXPLAIN |
两者输出格式不同 |
| 存储过程 |
支持 |
不支持 |
Hive 不支持存储过程 |
| 索引 |
支持 B+树等多种 |
仅有元数据索引(无普通索引) |
Hive 靠分区和分桶优化 |
九、快速对照表(常用)
| 你要做的事 |
MySQL |
Hive |
| 字符串长度(字符) |
CHAR_LENGTH(s) |
LENGTH(s) |
| 正则提取 |
REGEXP_SUBSTR(s, p) |
regexp_extract(s, p, 1) |
| 分组拼接 |
GROUP_CONCAT(col) |
CONCAT_WS(',', COLLECT_LIST(col)) |
| 日期加天 |
DATE_ADD(d, INTERVAL 1 DAY) |
DATE_ADD(d, 1) |
| 日期差(天) |
DATEDIFF(d1, d2) |
DATEDIFF(d1, d2) |
| 日期差(小时) |
TIMESTAMPDIFF(HOUR, d1, d2) |
(UNIX_TIMESTAMP(d2)-UNIX_TIMESTAMP(d1))/3600 |
| 空值替换 |
IFNULL(x, def) |
NVL(x, def) |
| 中位数 |
自己实现 |
PERCENTILE(col, 0.5) |
| 字符串拆成多行 |
递归 CTE |
LATERAL VIEW EXPLODE(SPLIT(s, ',')) |
| 提取 JSON |
JSON_EXTRACT(j, '$.key') |
get_json_object(j, '$.key') |
所有评论(0)