Hive 迁移到 StarRocks:58 个常用函数的改写清单
把 SQL 从 Hive 迁移到 StarRocks,表结构和语法通常一次就能改完,函数却容易漏改。例如 Hive 的 NVL,在 StarRocks 中要写成 IFNULL。同名函数也可能在参数顺序、NULL 处理或返回类型上不一样。
本文整理了 58 个数仓常用函数,其中 19 个需要改写,1 个在 StarRocks 中没有对应函数。另有 4 个函数在 Hive 中只能用标准 SQL 绕过,到 StarRocks 可以改用原生函数。每条结论都附有官方文档出处,最近一次核对是 2026-10-21。
需要改写的函数
| 函数 | Hive 写法 | StarRocks 写法 |
|---|---|---|
| ARRAY_DISTINCT | collect_set(x) |
array_distinct(array) |
| ARRAY_JOIN | concat_ws(SEP, array<string>) |
array_join(array, sep[, null_replace_str]) |
| COLLECT_LIST | collect_list(col) |
ARRAY_AGG(col [ORDER BY ...]) |
| COLLECT_SET | collect_set(col) |
ARRAY_AGG(DISTINCT col) |
| DATEADD | date_add(startdate, days) / add_months(startdate, n) |
TIMESTAMPADD(unit, n, datetime_expr) |
| DATETRUNC | trunc(date, 'MM') |
date_trunc('month', datetime) |
| EXPLODE | explode(array | map) |
FROM t, UNNEST(arr) AS u(x) |
| FROM_JSON | json_tuple(jsonStr, k1, k2, ...) |
parse_json(str) |
| GETDATE | current_timestamp |
NOW([p]) |
| LENGTH | length(string A) |
char_length(str) |
| MONTHS_BETWEEN | months_between(date1, date2) |
months_diff(expr1, expr2) |
| NVL | NVL(value, default_value) |
IFNULL(expr1, expr2) |
| POSEXPLODE | posexplode(ARRAY<T> a) |
无对应函数 |
| RLIKE | A RLIKE B |
regexp(expr, pattern) |
| SIZE | size(array_or_map) |
array_length(arr) / map_size(m) |
| SORT_ARRAY | sort_array(Array<T>) |
array_sort(array) |
| SPLIT_PART | split(str, pat)[n - 1] |
split_part(content, delimiter, field) |
| TO_DATE | to_date(from_unixtime(unix_timestamp(str, pattern))) |
str_to_date(str, format) |
| WM_CONCAT | concat_ws(',', collect_list(col)) |
GROUP_CONCAT([DISTINCT] expr [ORDER BY ...] [SEPARATOR sep]) |
StarRocks 写法说明
- ARRAY_DISTINCT:返回数组中元素的顺序可能与原数组不同。
- ARRAY_JOIN:只支持一维数组,不支持 DECIMAL 元素。不传 null_replace_str 时丢弃 NULL;sep 或 null_replace_str 为 NULL 时返回 NULL。
- COLLECT_LIST:在 StarRocks 文档中搜索不到 COLLECT_LIST。ARRAY_AGG 会保留 NULL,3.0 起支持 ORDER BY 指定元素顺序。
- COLLECT_SET:在 StarRocks 文档中搜索不到 COLLECT_SET。ARRAY_AGG_DISTINCT 是 ARRAY_AGG(DISTINCT) 的别名。ARRAY_AGG 会保留 NULL。
- DATEADD:单位写成关键字,例如 HOUR、DAY、MONTH,不加引号。TIMESTAMPADD 文档没有列出 QUARTER;按季度加减可以用 DATE_ADD(dt, INTERVAL n QUARTER)。
- DATETRUNC:单位在前且必须是常量。DATE 输入只能截断到 year、quarter、month、week、day。
- EXPLODE:UNNEST 是表函数,配合横向连接使用,不需要写 LATERAL。NULL 或空数组不输出行;3.2.7 起可以用 LEFT JOIN … ON TRUE 保留这些行。
- FROM_JSON:没有 FROM_JSON。parse_json 返回 JSON 类型,而不是 STRUCT 或 MAP。文档写明无法解析时返回 NULL;实测 4.1.6 中 ‘{bad’ 这类残缺 JSON 返回 NULL,但不带引号的普通文本(如 ‘not json’)会被当作 JSON 字符串返回。取字段可以接 json_query 或 -> 运算符。
- GETDATE:别名有 current_timestamp、localtime 和 localtimestamp,返回 DATETIME,默认精度到秒。3.1.6 起可以传 1~6 指定秒后的小数位数。结果受时区设置影响。
- LENGTH:LENGTH 返回的是字节数。按字符计数要用 char_length,别名 character_length,目前只支持 UTF-8。
- MONTHS_BETWEEN:函数列表中没有 MONTHS_BETWEEN。months_diff 返回 expr1 减 expr2 的月数,类型是 BIGINT,只精确到月;日期不存在时返回 NULL。
- NVL:条件函数列表中没有 NVL,只有 case、coalesce、if、ifnull 和 nullif。IFNULL 的结果类型与 expr1 一致。
- POSEXPLODE:UNNEST 文档中没有返回元素位置的参数或 WITH ORDINALITY 写法。
- RLIKE:匹配返回 1,否则返回 0,任一参数为 NULL 时返回 NULL。
- SIZE:数组用 array_length,别名 cardinality,3.0 起提供,NULL 元素也计入长度,输入为 NULL 时返回 NULL。Map 用 map_size,2.5 起提供,别名同样是 cardinality。
- SORT_ARRAY:升序排列,NULL 放在开头。4.0 起可以传 Lambda 比较函数自定义顺序。
- SPLIT_PART:正数从开头数,负数从末尾数,-1 表示最后一段。下标越界时,官方示例返回空字符串。
- TO_DATE:StarRocks 的 to_date 只接受 DATETIME 并取日期部分,不能解析字符串。按格式解析用 str_to_date,格式符与 date_format 相同;格式只含日期时返回 DATE,否则返回 DATETIME。
- WM_CONCAT:默认分隔符是逗号,跳过 NULL。结果长度受 group_concat_max_len 限制,默认 1,024 个字符,超出部分会被截断。
可以改用原生函数
下面这些函数在 Hive 中没有原生实现,一般用标准 SQL 绕过。原写法在 StarRocks 中仍然能运行,不改也可以。
| 函数 | Hive 写法 | StarRocks 写法 |
|---|---|---|
| ANY_VALUE | max(col) |
ANY_VALUE(expr) |
| APPROX_COUNT_DISTINCT | COUNT(DISTINCT col) |
APPROX_COUNT_DISTINCT(expr) |
| DAYOFWEEK | extract(dayofweek FROM ts) |
dayofweek(date) |
| MAX_BY | ROW_NUMBER() OVER (PARTITION BY ... ORDER BY y DESC) = 1 |
max_by(x, y) |
迁移注意事项
ARRAY_DISTINCT 数组去重
- StarRocks 文档说明去重后的顺序可能变化。依赖元素顺序(例如取第一个元素)的逻辑,迁移到 StarRocks 时要先排序或改写。
- Hive 内置函数文档中没有 array_distinct,旧 SQL 常用 explode 加 collect_set 去重,迁移到其他引擎时可以直接改成 ARRAY_DISTINCT。
ARRAY_JOIN 数组拼接成字符串
- Hive 的 concat_ws 只接受 array
,整数数组要先转换;Flink 的 ARRAY_JOIN 也要求元素是字符串。MaxCompute、Doris 会自动把元素转成字符串。 - StarRocks 不支持 DECIMAL 元素,也只支持一维数组,迁移前要检查数组类型。
COLLECT_LIST 聚合为数组
- 不要依赖数组元素的顺序。MaxCompute 文档建议用 SORT_ARRAY 排序;StarRocks 可以直接写 ARRAY_AGG(x ORDER BY y)。
- StarRocks 的 ARRAY_AGG 保留 NULL,MaxCompute 和 Doris 的 COLLECT_LIST 丢弃 NULL,数组长度可能不一致。
COLLECT_SET 去重聚合为数组
- NULL 的处理不同:MaxCompute、Doris 会丢弃 NULL,StarRocks 的 ARRAY_AGG 会保留 NULL。迁移到 StarRocks 后数组里可能多出 NULL 元素。
DATEADD 按单位加减日期
- MaxCompute 按月加减时,如果目标月份没有对应日期,结果取当月最后一天。StarRocks 的 DATE_ADD 遇到不存在的日期返回 NULL。
DATETRUNC 日期截断
- 参数顺序不同:MaxCompute 是日期在前,Hologres、StarRocks 和 Spark 是单位在前,Doris 两种都接受。
- Hive 的 trunc 只能截断到月和年,按周、按季度汇总需要自己计算。
EXPLODE 数组展开为多行
- 空数组和 NULL 数组的行会被直接丢掉:MaxCompute、Doris 的 EXPLODE 和 StarRocks 的 UNNEST 都是这样。需要保留时,Doris 和 Spark 用 EXPLODE_OUTER,StarRocks 3.2.7 起用 LEFT JOIN UNNEST(…) ON TRUE。
- 需要元素位置时,Hive 和 Spark 的 posexplode 位置从 0 开始,Flink 的 WITH ORDINALITY 从 1 开始,迁移时要调整下标。
FROM_JSON 按 schema 解析 JSON
- StarRocks 的 parse_json 和 Doris 的 JSON_PARSE 返回的是 JSON 类型,下游需要 STRUCT 或 MAP 时要再做一次转换,不能直接替换 from_json。
- 非法 JSON 的处理不同:StarRocks 的 parse_json 对残缺 JSON 返回 NULL,但会把普通文本当作 JSON 字符串接受;Doris 的 JSON_PARSE 直接报错。脏数据较多的表,在 Doris 中改用 JSON_PARSE_ERROR_TO_NULL。
GETDATE 获取当前时间
- 返回类型不同:MaxCompute、StarRocks 和 Doris 返回 DATETIME,Hologres 的 NOW 带时区(文档把不带时区的版本单独列为 LOCALTIMESTAMP),Flink 返回 TIMESTAMP_LTZ(3)。直接写入字符串或 DATETIME 字段时,格式可能变化。
- 精度不同:MaxCompute 默认到秒,StarRocks 和 Doris 默认到秒、可传参数到微秒,Flink 到毫秒。用当前时间做去重或比较时要注意小数部分。
- Hive 和 Spark 的 current_timestamp 可以不带括号,Doris 文档中的写法是 current_timestamp()。迁移时统一写 NOW() 更容易对齐。
LENGTH 字符串长度
- StarRocks 和 Doris 的 LENGTH 返回字节数。像 WHERE LENGTH(name) > 10 这样的条件,迁移后对中文内容会多筛出很多行,而且不会报错。
- 按字符计数统一写 CHAR_LENGTH 最稳妥:Hologres、StarRocks、Doris、Flink 都支持,Hive 2.2.0 起也支持(char_length 是 character_length 的简写)。
MONTHS_BETWEEN 相差月数
- StarRocks 的 months_diff、Flink 的 TIMESTAMPDIFF 和 Hologres 的 EXTRACT 写法都只返回整数月,原 SQL 中依赖小数部分的计算(例如按 0.5 个月判断)需要重新设计。
- 时间部分的处理不同:Doris 只看日期,Hive 会把时间部分算进小数,Spark 在同一天或都是月末时忽略时间。同样的输入可能得到不同的小数。
- 舍入不同:Hive 和 Spark 默认保留 8 位小数,MaxCompute 返回完整的 DOUBLE,Doris 由 round_type 控制。和原结果做等值比较前,先统一 ROUND。
NVL 空值替换
- 迁移到 Hologres、StarRocks 或 Flink SQL 时,统一改写为 COALESCE 最省事,因为 COALESCE 在七个引擎中都可用。
POSEXPLODE 带下标展开数组
- Hologres、StarRocks 和 Flink 没有带位置的展开函数。如果只需要元素,改用 UNNEST;如果依赖位置,需要在入库前补充位置信息,或用其他方式改写。
- Hive 和 Doris 需要写在 LATERAL VIEW 中,列别名的写法要按各自文档调整。
RLIKE 正则匹配判断
- StarRocks 的 regexp 返回 1 或 0,写在 WHERE 中可以直接用,但写入布尔列或与 true 比较时要注意类型。
- Doris 默认用 RE2 语法,不支持 (?=…) 这类零宽断言。从 Hive 或 Spark 的 Java 正则迁移时,要先确认是否用到这些写法。
SIZE 数组和 Map 元素个数
- StarRocks 和 Doris 区分数组和 Map 函数。从 MaxCompute 或 Hive 迁移时,要按字段类型分别改成 array_length、map_size 或 ARRAY_SIZE、MAP_SIZE。
- StarRocks 和 Doris 文档写明 NULL 元素也计入个数。需要只统计非空元素时,要先过滤再计数。
SORT_ARRAY 数组排序
- Spark 有两个排序函数:sort_array 升序时把 NULL 放在开头,array_sort 把 NULL 放在末尾。从 MaxCompute 或 Hive 迁移时应使用 sort_array,结果才一致。
- 降序的写法不同:MaxCompute 和 Spark 传第二个参数,Flink 传 ascending_order,Doris 用 ARRAY_REVERSE_SORT,Hive 和 Hologres 的函数只能升序。
SPLIT_PART 按分隔符取第 N 段
- 下标越界时结果不同:MaxCompute、StarRocks 和 Spark 返回空字符串,Hologres 和 Doris 返回 NULL。下游用 IS NULL 或 = ‘’ 判断时,迁移后结果可能变化。
- Hive 的 split 按正则切分。分隔符是 .、| 这类正则特殊字符时,要写成 split(s, ‘\.’),否则结果不对。
- Hive 的数组下标和 Flink 的 SPLIT_INDEX 都从 0 开始。从 SPLIT_PART 改写时要把下标减 1。
- 取最后一段时,StarRocks 和 Spark 可以直接传 -1。MaxCompute 要求下标大于 0,不能这样写。
TO_DATE 字符串转日期
- 同名不同义:把 MaxCompute 的 TO_DATE(‘20261013’, ‘yyyymmdd’) 直接搬到 StarRocks、Doris 或 Hive 会报错或得到错误结果,需要改用 str_to_date 或 unix_timestamp。
WM_CONCAT 分组拼接字符串
- StarRocks 的 GROUP_CONCAT 默认最多 1,024 个字符,超出部分不报错直接截断。长列表需要先调大 group_concat_max_len。
- 不写排序时,各引擎拼接的顺序都不固定。需要稳定结果时,MaxCompute 写 WITHIN GROUP (ORDER BY …),StarRocks 和 Doris 在 GROUP_CONCAT 内写 ORDER BY。
- StarRocks 3.0.6 和 3.1.3 起,GROUP_CONCAT 必须用 SEPARATOR 关键字声明分隔符。
APPROX_COUNT_DISTINCT 近似去重计数
- 改写成 Hive 或 Flink 的 COUNT(DISTINCT) 后结果是精确值,但资源消耗会明显变大,大数据量下要评估内存和运行时间。
DAYOFWEEK 星期几
- Hive 的内置函数文档没有 dayofweek,只能用 Hive 2.2.0 起提供的 extract(dayofweek FROM …)。
MAX_BY 取最大值对应的列
- 并列最大时结果不确定:MaxCompute 随机返回一行,StarRocks 返回最先遇到的一行。需要稳定结果时,改用 ROW_NUMBER 并在 ORDER BY 中加上唯一的次排序列。
写法相同的函数
以下 35 个函数在两个引擎中写法相同,可以直接迁移。参数和边界行为的细节见各函数的对照页。
ADD_MONTHS、ARRAY_CONTAINS、COALESCE、CONCAT、CONCAT_WS、DATE_ADD、DATE_FORMAT、DATE_SUB、DATEDIFF、DECODE、FIRST_VALUE、FROM_UNIXTIME、GET_JSON_OBJECT、GREATEST、IF、INSTR、LAG、LAST_DAY、LAST_VALUE、LEAD、LPAD、MD5、NULLIF、PERCENTILE_APPROX、REGEXP_EXTRACT、REGEXP_REPLACE、REPLACE、ROW_NUMBER、SPLIT、STR_TO_MAP、SUBSTR、SUBSTRING_INDEX、TO_CHAR、UNIX_TIMESTAMP、WEEKOFYEAR
说明
数据来自开源数据集 sql-dialect-functions(CC BY 4.0)。完整对照见在线清单,现有 SQL 可以用迁移检查器检查。