SQL 方言通

首页 / 工具 / 迁移清单 / Hologres → Spark SQL

Hologres 迁移到 Spark SQL 的函数改写清单

从 Hologres 迁移到 Spark SQL 时,在 Hologres 有对应写法的 43 个常用函数中,18 个需要改写(其中 1 个在 Spark SQL 没有对应函数),另有 8 个可以改用 Spark SQL 的原生函数。逐个列出两边写法和注意事项。

需要改写的函数 · 可以改用原生函数 · 迁移注意事项 · 可以直接用的函数 · 反向:Spark SQL 迁移到 Hologres

需要改写的函数

函数Hologres 写法Spark SQL 写法Spark SQL 说明
ADD_MONTHSd + interval '1 month'支持 add_months(start_date, num_months)Spark 1.5.0 起提供。add_months('2016-08-31', 1) 返回 2016-09-30。
COLLECT_LISTARRAY_AGG(expression)支持 collect_list(expr)Spark 2.0.0 起提供,结果顺序不确定。3.3.0 起另有同义的 array_agg。
COLLECT_SETARRAY_AGG(DISTINCT expression)支持 collect_set(expr)Spark 2.0.0 起提供。文档注明结果顺序取决于 shuffle 后的行序,是不确定的。
DATE_ADDDATEADD(d, num, 'day')支持 date_add(start_date, num_days)Spark 1.5.0 起提供。3.4.0 起另有同义的 dateadd。
DATE_FORMATTO_CHAR(timestamp, 'YYYY-MM-DD HH24:MI:SS')支持 date_format(timestamp, fmt)Spark 1.5.0 起提供。
DATE_SUBd - interval '1 day'支持 date_sub(start_date, num_days)Spark 1.5.0 起提供。
DATEADDDATEADD(d, num, str)需改写 ts + INTERVAL n HOURSpark 3.4.0 起有 dateadd(start_date, num_days),但只能加天数,没有单位参数。按小时、月等单位加减用 INTERVAL 字面量,按月也可以用 add_months。
EXPLODEUNNEST(anyarray)支持 explode(expr)Spark 1.0.0 起提供。数组默认列名为 col,map 为 key 和 value。需要保留空数组的行时用 explode_outer。
FROM_JSONjson_str::jsonb ->> 'key'支持 from_json(jsonStr, schema[, options])Spark 2.2.0 起提供。schema 用 DDL 字符串,例如 'a INT, b DOUBLE'。options 可以指定 timestampFormat 等解析选项。
FROM_UNIXTIMETO_TIMESTAMP(seconds)支持 from_unixtime(unix_time[, fmt])Spark 1.5.0 起提供,结果按会话时区显示。
GETDATENOW() 或 CURRENT_TIMESTAMP别名 current_timestamp() 或 now()返回查询开始执行时的时间戳,同一查询中各次调用结果相同。3.4.0 起还有不带时区的 localtimestamp()。
INSTRSTRPOS(str, substr)支持 instr(str, substr)Spark 1.5.0 起提供,下标从 1 开始。需要起始位置时用 locate(substr, str, pos)。
MAX_PTMAX_PT('table_name')不支持 函数索引中没有 MAX_PT。改写为 WHERE pt = (SELECT MAX(pt) FROM t)。
PERCENTILE_APPROXAPPROX_PERCENTILE(p) WITHIN GROUP (ORDER BY col)支持 percentile_approx(col, percentage[, accuracy])Spark 2.1.0 起提供,别名 approx_percentile。accuracy 默认 10000,相对误差为 1.0/accuracy。返回排序后满足条件的最小值,percentage 可以传数组。
REGEXP_EXTRACT(REGEXP_MATCH(str, pattern))[n]支持 regexp_extract(str, regexp[, idx])Spark 1.5.0 起提供。idx 默认为 1,为 0 时返回整个匹配。使用 Java 正则,字符串字面量会先被 SQL 解析器反转义,文档建议用 r 前缀的原始字符串,例如 r'(\d+)'。
SIZEARRAY_LENGTH(arr, 1)支持 size(expr)Spark 1.5.0 起提供,同时有别名 cardinality。输入为 NULL 时,只有关闭 ANSI 模式并开启 spark.sql.legacy.sizeOfNull 才返回 -1,否则返回 NULL。最新文档写明默认配置下返回 NULL。
SORT_ARRAYARRAY_SORT(anyarray)支持 sort_array(array[, ascendingOrder])Spark 1.5.0 起提供。升序时 NULL 在开头,降序时 NULL 在末尾。另有 array_sort,它把 NULL 放在末尾,3.0.0 起支持比较函数。
SPLITREGEXP_SPLIT_TO_ARRAY(str, pattern)支持 split(str, regex[, limit])Spark 1.5.0 起提供,按正则拆分,limit 限制数组的最大长度。

可以改用原生函数

下面的函数在 Hologres 中只能用替代写法,Spark SQL 有对应的函数。原来的写法通常仍能运行,换成原生函数会更简洁。

函数Hologres 写法Spark SQL 写法Spark SQL 说明
ANY_VALUEMAX(col)支持 any_value(expr[, isIgnoreNull])Spark 3.4.0 起提供,结果不确定。isIgnoreNull 为 true 时只返回非 NULL 值,默认可能返回 NULL。
DAYOFWEEKEXTRACT(DOW FROM ts) + 1支持 dayofweek(date)Spark 2.3.0 起提供,周日为 1,周六为 7。weekday(date) 则以周一为 0、周日为 6。
DECODECASE expr WHEN search THEN result ... ELSE default END支持 decode(expr, search, result [, search, result ] ... [, default])多值匹配写法 3.2.0 起支持。没有匹配且省略 default 时返回 NULL。同名的 decode(bin, charset) 用于按字符集解码。
MONTHS_BETWEEN(EXTRACT(YEAR FROM a) - EXTRACT(YEAR FROM b)) * 12 + EXTRACT(MONTH FROM a) - EXTRACT(MONTH FROM b)支持 months_between(timestamp1, timestamp2[, roundOff])Spark 1.5.0 起提供。同一天或都是月末时忽略时间部分,否则按每月 31 天计算,默认保留 8 位小数,roundOff 为 false 时不舍入。
NVLCOALESCE(value, default_value)支持 nvl(expr1, expr2)Spark 2.0.0 起提供,同时有 ifnull、nvl2 和 coalesce。
SUBSTRSUBSTRING(str FROM start FOR len)支持 substr(str, pos[, len])Spark 1.5.0 起提供,与 substring 相同。负数从末尾倒数:substr('Spark SQL', -3) 返回 SQL。
UNIX_TIMESTAMPEXTRACT(EPOCH FROM ts)支持 unix_timestamp([timeExp[, fmt]])Spark 1.5.0 起提供,默认格式 yyyy-MM-dd HH:mm:ss。另有 to_unix_timestamp。
WEEKOFYEAREXTRACT(WEEK FROM ts)支持 weekofyear(date)周一为一周的开始,第一周是第一个超过 3 天的周。

迁移注意事项

以下内容摘自各函数页中提到 Hologres 或 Spark SQL 的注意事项。

ADD_MONTHS 按月加减

DATE_FORMAT 日期格式化

DATEADD 按单位加减日期

EXPLODE 数组展开为多行

FROM_UNIXTIME 时间戳转日期

GETDATE 获取当前时间

INSTR 查找子串位置

PERCENTILE_APPROX 近似分位数

REGEXP_EXTRACT 正则提取

SIZE 数组和 Map 元素个数

SORT_ARRAY 数组排序

SPLIT 字符串拆分

ANY_VALUE 取组内任意值

DAYOFWEEK 星期几

DECODE 多值匹配

MONTHS_BETWEEN 相差月数

NVL 空值替换

SUBSTR 截取子串

UNIX_TIMESTAMP 日期转时间戳

WEEKOFYEAR 一年中的第几周

可以直接用的函数

下面 17 个函数在两个引擎中写法相同。参数、返回值和边界情况仍可能不同,点开函数页查看细节。

相关页面:Hologres 函数写法 · Spark SQL 函数写法 · 全部迁移清单 · 用 SQL 迁移检查器检查自己的 SQL