SQL 方言通

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

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

从 Flink SQL 迁移到 Spark SQL 时,在 Flink SQL 有对应写法的 43 个常用函数中,23 个需要改写,另有 4 个可以改用 Spark SQL 的原生函数。逐个列出两边写法和注意事项。

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

需要改写的函数

函数Flink SQL 写法Spark SQL 写法Spark SQL 说明
ADD_MONTHSTIMESTAMPADD(MONTH, n, timepoint)支持 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_ADDTIMESTAMPADD(DAY, n, timepoint)支持 date_add(start_date, num_days)Spark 1.5.0 起提供。3.4.0 起另有同义的 dateadd。
DATE_SUBTIMESTAMPADD(DAY, -n, timepoint)支持 date_sub(start_date, num_days)Spark 1.5.0 起提供。
DATEADDTIMESTAMPADD(unit, n, timepoint)需改写 ts + INTERVAL n HOURSpark 3.4.0 起有 dateadd(start_date, num_days),但只能加天数,没有单位参数。按小时、月等单位加减用 INTERVAL 字面量,按月也可以用 add_months。
DATEDIFFTIMESTAMPDIFF(DAY, timepoint1, timepoint2)支持 datediff(endDate, startDate)Spark 1.5.0 起提供。3.4.0 起另有同义的 date_diff。
DATETRUNCFLOOR(timepoint TO MONTH)需改写 date_trunc('MONTH', ts)date_trunc 从 2.3.0 起提供,单位在前,返回 timestamp。只需要日期时可以用 trunc(date, fmt)。
EXPLODECROSS JOIN UNNEST(arr) AS t(x)支持 explode(expr)Spark 1.0.0 起提供。数组默认列名为 col,map 为 key 和 value。需要保留空数组的行时用 explode_outer。
FROM_JSONJSON_VALUE(json, path) / JSON_QUERY(json, path)支持 from_json(jsonStr, schema[, options])Spark 2.2.0 起提供。schema 用 DDL 字符串,例如 'a INT, b DOUBLE'。options 可以指定 timestampFormat 等解析选项。
GET_JSON_OBJECTJSON_VALUE(json, path)支持 get_json_object(json_txt, path)从 Spark 1.5.0 起提供。
GETDATECURRENT_TIMESTAMP 或 NOW()别名 current_timestamp() 或 now()返回查询开始执行时的时间戳,同一查询中各次调用结果相同。3.4.0 起还有不带时区的 localtimestamp()。
LAST_DAYTIMESTAMPADD(DAY, -1, TIMESTAMPADD(MONTH, 1, FLOOR(ts TO MONTH)))支持 last_day(date)Spark 1.5.0 起提供。
LENGTHCHAR_LENGTH(string)支持 length(expr)返回字符数,包含末尾的空格;对二进制数据返回字节数。字节数用 octet_length。
MONTHS_BETWEENTIMESTAMPDIFF(MONTH, start, end)支持 months_between(timestamp1, timestamp2[, roundOff])Spark 1.5.0 起提供。同一天或都是月末时忽略时间部分,否则按每月 31 天计算,默认保留 8 位小数,roundOff 为 false 时不舍入。
NVLIFNULL(input, null_replacement)支持 nvl(expr1, expr2)Spark 2.0.0 起提供,同时有 ifnull、nvl2 和 coalesce。
PERCENTILE_APPROXPERCENTILE(expr, percentage[, frequency])支持 percentile_approx(col, percentage[, accuracy])Spark 2.1.0 起提供,别名 approx_percentile。accuracy 默认 10000,相对误差为 1.0/accuracy。返回排序后满足条件的最小值,percentage 可以传数组。
SIZECARDINALITY(array_or_map)支持 size(expr)Spark 1.5.0 起提供,同时有别名 cardinality。输入为 NULL 时,只有关闭 ANSI 模式并开启 spark.sql.legacy.sizeOfNull 才返回 -1,否则返回 NULL。最新文档写明默认配置下返回 NULL。
SORT_ARRAYARRAY_SORT(array[, ascending_order[, null_first]])支持 sort_array(array[, ascendingOrder])Spark 1.5.0 起提供。升序时 NULL 在开头,降序时 NULL 在末尾。另有 array_sort,它把 NULL 放在末尾,3.0.0 起支持比较函数。
SPLIT_PARTSPLIT_INDEX(str, delimiter, n - 1)支持 split_part(str, delimiter, partNum)Spark 3.3.0 起提供。下标从 1 开始,负数从末尾数。越界返回空字符串,partNum 为 0 时报错,分隔符为空字符串时不切分。
TO_CHARDATE_FORMAT(timestamp, 'yyyy-MM-dd HH:mm:ss')支持 to_char(expr, format)Spark 3.4.0 起提供。4.0 文档写明 expr 可以是日期时间,此时 format 使用 Java 风格格式符;更早的版本请按所用版本文档确认。也可以直接用 date_format。
WEEKOFYEARWEEK(date)支持 weekofyear(date)周一为一周的开始,第一周是第一个超过 3 天的周。
WM_CONCATLISTAGG(expression[, separator])需改写 string_agg(expr[, delimiter]) WITHIN GROUP (ORDER BY ...)string_agg 和 listagg 从 Spark 4.0.0 起提供。更早的版本用 concat_ws(',', collect_list(expr))。

可以改用原生函数

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

函数Flink SQL 写法Spark SQL 写法Spark SQL 说明
ANY_VALUEFIRST_VALUE(expression)支持 any_value(expr[, isIgnoreNull])Spark 3.4.0 起提供,结果不确定。isIgnoreNull 为 true 时只返回非 NULL 值,默认可能返回 NULL。
APPROX_COUNT_DISTINCTCOUNT(DISTINCT expr)支持 approx_count_distinct(expr[, relativeSD])Spark 1.6.0 起提供,基于 HyperLogLog++。relativeSD 是允许的最大相对标准差。
DECODECASE expr WHEN search THEN result ... ELSE default END支持 decode(expr, search, result [, search, result ] ... [, default])多值匹配写法 3.2.0 起支持。没有匹配且省略 default 时返回 NULL。同名的 decode(bin, charset) 用于按字符集解码。
MAX_BYROW_NUMBER() OVER (PARTITION BY ... ORDER BY y DESC) = 1支持 max_by(x, y[, k])传入 k 时返回 y 最大的前 k 个 x 组成的数组,k 最大 100,000。y 全为 NULL 时返回 NULL。

迁移注意事项

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

ADD_MONTHS 按月加减

DATEADD 按单位加减日期

DATEDIFF 日期差

DATETRUNC 日期截断

EXPLODE 数组展开为多行

GETDATE 获取当前时间

LENGTH 字符串长度

MONTHS_BETWEEN 相差月数

NVL 空值替换

PERCENTILE_APPROX 近似分位数

SIZE 数组和 Map 元素个数

SORT_ARRAY 数组排序

SPLIT_PART 按分隔符取第 N 段

TO_CHAR 日期转字符串

ANY_VALUE 取组内任意值

APPROX_COUNT_DISTINCT 近似去重计数

DECODE 多值匹配

可以直接用的函数

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

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