已弃用 DuckDB 1.3.0 弃用了旧的 lambda 单箭头语法(
x -> x + 1
),转而支持 Python 风格的语法(lambda x : x + 1
)。DuckDB 1.3.0 还引入了一个新设置来配置 lambda 语法。
SET lambda_syntax = 'DEFAULT'; SET lambda_syntax = 'ENABLE_SINGLE_ARROW'; SET lambda_syntax = 'DISABLE_SINGLE_ARROW';
目前,
DEFAULT
启用两种语法风格,即旧的单箭头语法和 Python 风格的语法。DuckDB 1.4.0 将是最后一个在未明确启用单箭头语法的情况下支持它的版本。
DuckDB 1.5.0 默认禁用单箭头语法。
DuckDB 1.6.0 将移除
lambda_syntax
标志并完全弃用单箭头语法,因此旧的行为将不再可能。
Lambda 函数允许在查询中使用更复杂、更灵活的表达式。DuckDB 支持多种作用于 LIST
(列表)的标量函数,并接受形如 lambda 参数1, 参数2, ... : 表达式
的 lambda 函数作为参数。如果 lambda 函数只有一个参数,则可以省略括号。参数可以有任何名称。例如,以下都是有效的 lambda 函数:
lambda param : param > 1
lambda s : contains(concat(s, 'DB'), 'duck')
lambda acc, x : acc + x
接受 Lambda 函数的标量函数
名称 | 描述 |
---|---|
list_transform(list, lambda(x)) |
返回一个列表,该列表是应用 lambda 函数到输入列表的每个元素的结果。返回类型由 lambda 函数的返回类型定义。请参阅 list_transform 示例。 |
list_filter(list, lambda(x)) |
从输入列表中筛选出 lambda 函数返回 true 的元素,并构造一个新列表。DuckDB 必须能够将 lambda 函数的返回类型转换为 BOOL 。 list_filter 的返回类型与输入列表相同。请参阅 list_filter 示例。 |
list_reduce(list, lambda(x, y)[, initial_value] |
通过在当前结果和下一个列表元素上执行 lambda 函数,将输入列表的所有元素归约(reduce)为一个单一的标量值。lambda 函数有一个可选的 initial_value 参数。请参阅 list_reduce 示例或详细信息。 |
list_transform(list, lambda(x))
描述 | 返回一个列表,该列表是应用 lambda 函数到输入列表的每个元素的结果。返回类型由 lambda 函数的返回类型定义。请参阅 list_transform 示例。 |
示例 | list_transform([4, 5, 6], lambda x : x + 1) |
结果 | [5, 6, 7] |
别名 | array_transform , apply , list_apply , array_apply |
list_filter(list, lambda(x))
描述 | 从输入列表中筛选出 lambda 函数返回 true 的元素,并构造一个新列表。DuckDB 必须能够将 lambda 函数的返回类型转换为 BOOL 。 list_filter 的返回类型与输入列表相同。请参阅 list_filter 示例。 |
示例 | list_filter([4, 5, 6], lambda x : x > 4) |
结果 | [5, 6] |
别名 | array_filter , filter |
list_reduce(list, lambda(x, y)[, initial_value]
描述 | 通过在当前结果和下一个列表元素上执行 lambda 函数,将输入列表的所有元素归约(reduce)为一个单一的标量值。lambda 函数有一个可选的 initial_value 参数。请参阅 list_reduce 示例或详细信息。 |
示例 | list_reduce([1, 2, 3], lambda x, y : x + y, 100) |
结果 | 106 |
别名 | array_reduce , reduce |
嵌套 Lambda 函数
所有标量函数都可以任意嵌套。例如,嵌套 lambda 函数以获取列表偶数元素的平方:
SELECT list_transform(
list_filter([0, 1, 2, 3, 4, 5], lambda x: x % 2 = 0),
lambda y: y * y
);
[0, 4, 16]
嵌套 lambda 函数将第一个列表的每个元素添加到第二个列表的和中。
SELECT list_transform(
[1, 2, 3],
lambda x :
list_reduce([4, 5, 6], lambda a, b: a + b) + x
);
[16, 17, 18]
作用域
Lambda 函数遵循以下作用域规则:
- 内部 lambda 参数
- 外部 lambda 参数
- 列名
- 宏参数
CREATE TABLE tbl (x INTEGER);
INSERT INTO tbl VALUES (10);
SELECT list_apply(
[1, 2],
lambda x: list_apply([4], lambda x: x + tbl.x)[1] + x
)
FROM tbl;
[15, 16]
索引作为参数
所有 lambda 函数都接受一个可选的额外参数,该参数表示当前元素的索引。这始终是 lambda 函数的最后一个参数(例如,(x, i)
中的 i
),并且是基于 1 的索引(即,第一个元素的索引是 1)。
获取所有大于其索引的元素
SELECT list_filter([1, 3, 1, 5], lambda x, i: x > i);
[3, 5]
示例
list_transform
示例
将每个列表元素加一
SELECT list_transform([1, 2, NULL, 3], lambda x: x + 1);
[2, 3, NULL, 4]
转换字符串
SELECT list_transform(['Duck', 'Goose', 'Sparrow'], lambda s: concat(s, 'DB'));
[DuckDB, GooseDB, SparrowDB]
将 lambda 函数与其他函数结合
SELECT list_transform([5, NULL, 6], lambda x: coalesce(x, 0) + 1);
[6, 1, 7]
list_filter
示例
过滤掉负值
SELECT list_filter([5, -6, NULL, 7], lambda x: x > 0);
[5, 7]
可被 2 和 5 整除
SELECT list_filter(
list_filter([2, 4, 3, 1, 20, 10, 3, 30], lambda x: x % 2 = 0),
lambda y: y % 5 = 0
);
[20, 10, 30]
结合 range(...)
构造列表
SELECT list_filter([1, 2, 3, 4], lambda x: x > #1) FROM range(4);
[1, 2, 3, 4]
[2, 3, 4]
[3, 4]
[4]
list_reduce
示例
所有列表元素的和
SELECT list_reduce([1, 2, 3, 4], lambda acc, x: acc + x);
10
仅当列表元素大于 2 时才求和
SELECT list_reduce(
list_filter([1, 2, 3, 4], lambda x: x > 2),
lambda acc, x: acc + x
);
7
连接所有列表元素
SELECT list_reduce(['DuckDB', 'is', 'awesome'], lambda acc, x: concat(acc, ' ', x));
DuckDB is awesome
连接带索引的元素,无初始值
SELECT list_reduce(
['a', 'b', 'c', 'd'],
lambda x, y, i: x || ' - ' || CAST(i AS VARCHAR) || ' - ' || y
);
a - 2 - b - 3 - c - 4 - d
连接带索引的元素,有初始值
SELECT list_reduce(
['a', 'b', 'c', 'd'],
lambda x, y, i: x || ' - ' || CAST(i AS VARCHAR) || ' - ' || y, 'INITIAL'
);
INITIAL - 1 - a - 2 - b - 3 - c - 4 - d
限制
lambda 表达式中目前不支持子查询。例如:
SELECT list_apply([1, 2, 3], lambda x: (SELECT 42) + x);
Binder Error:
subqueries in lambda expressions are not supported