跳到主要内容

星号表达式

语法

* 表达式可在 SELECT 语句中使用,用于选择 FROM 子句中投影出的所有列。

SELECT *
FROM tbl;

TABLE.*STRUCT.*

* 表达式前可以加上表名,从而只选择该表中的列。

SELECT tbl.*
FROM tbl
JOIN other_tbl USING (id);

类似地,* 表达式也可用于把 struct 中的所有键提取为独立列。 当上一步操作产生了形状未知的 struct,或者查询需要处理 struct 中任意可能出现的键时,这一能力尤其有用。 关于如何使用 struct 的更多细节,请参阅 STRUCT data typeSTRUCT functions 页面。

例如:

SELECT st.* FROM (SELECT {'x': 1, 'y': 2, 'z': 3} AS st);
xyz
123

EXCLUDE 子句

EXCLUDE 允许你从 * 表达式中排除指定列。

SELECT * EXCLUDE (col)
FROM tbl;

REPLACE 子句

REPLACE 允许你用其他表达式替换指定列。

SELECT * REPLACE (col1 / 1_000 AS col1, col2 / 1_000 AS col2)
FROM tbl;

RENAME 子句

RENAME 允许你重命名指定列。

SELECT * RENAME (col1 AS height, col2 AS width)
FROM tbl;

通过模式匹配运算符筛选列

pattern matching operators LIKEGLOBSIMILAR TO 及其变体允许你通过列名模式匹配来选择列。

SELECT * LIKE 'col%'
FROM tbl;
SELECT * GLOB 'col*'
FROM tbl;
SELECT * SIMILAR TO 'col.'
FROM tbl;

COLUMNS 表达式

COLUMNS 表达式与普通星号表达式类似,但还允许你对得到的这些列统一执行同一个表达式。

CREATE TABLE numbers (id INTEGER, number INTEGER);
INSERT INTO numbers VALUES (1, 10), (2, 20), (3, NULL);
SELECT min(COLUMNS(*)), count(COLUMNS(*)) FROM numbers;
idnumberidnumber
11032
SELECT
min(COLUMNS(* REPLACE (number + id AS number))),
count(COLUMNS(* EXCLUDE (number)))
FROM numbers;
idmin(number := (number + id))id
1113

只要包含相同的星号表达式,COLUMNS 表达式还可以互相组合:

SELECT COLUMNS(*) + COLUMNS(*) FROM numbers;
idnumber
220
440
6NULL

WHERE 子句中的 COLUMNS 表达式

COLUMNS 表达式也可以用于 WHERE 子句。条件会应用到所有列,并使用逻辑 AND 运算符组合。

SELECT *
FROM (
SELECT 'a', 'a'
UNION ALL
SELECT 'a', 'b'
UNION ALL
SELECT 'b', 'b'
) _(x, y)
WHERE COLUMNS(*) = 'a'; -- equivalent to: x = 'a' AND y = 'a'
xy
aa

如果要用逻辑 OR 组合条件,可以把 COLUMNS 表达式通过 UNPACK 展开到可变参数函数 greatest 中。

SELECT *
FROM (
SELECT 'a', 'a'
UNION ALL
SELECT 'a', 'b'
UNION ALL
SELECT 'b', 'b'
) _(x, y)
WHERE greatest(UNPACK(COLUMNS(*) = 'a')); -- equivalent to: x = 'a' OR y = 'a'
xy
aa
ab

COLUMNS 表达式中的正则表达式

COLUMNS 表达式目前不支持模式匹配运算符,但支持正则匹配:只需用字符串常量替代星号即可。

SELECT COLUMNS('(id|numbers?)') FROM numbers;
idnumber
110
220
3NULL

COLUMNS 表达式中使用正则重命名列

可以使用正则表达式捕获组的匹配结果来重命名匹配到的列。 捕获组从 1 开始编号;\0 表示原始列名。

例如,若要仅保留列名前三个字符,可执行:

SELECT COLUMNS('(\w{3}).*') AS '\1' FROM numbers;
idnum
110
220
3NULL

若要去掉列名中间的冒号(:)字符,可执行:

CREATE TABLE tbl ("Foo:Bar" INTEGER, "Foo:Baz" INTEGER, "Foo:Qux" INTEGER);
SELECT COLUMNS('(\w*):(\w*)') AS '\1\2' FROM tbl;

若要把原始列名加入表达式别名,可执行:

SELECT min(COLUMNS(*)) AS "min_\0" FROM numbers;
min_idmin_number
110

COLUMNS Lambda 函数

COLUMNS 也支持传入 lambda 函数。该函数会对 FROM 子句中的所有列进行计算,只有匹配 lambda 条件的列会被返回。这样你就可以执行任意表达式来筛选并重命名列。

SELECT COLUMNS(lambda c: c LIKE '%num%') FROM numbers;
number
10
20
NULL

COLUMNS 列表

COLUMNS 还支持传入列名列表。

SELECT COLUMNS(['id', 'num']) FROM numbers;
idnum
110
220
3NULL

解包 COLUMNS 表达式

通过用 UNPACK 包裹 COLUMNS 表达式,列会被展开到其父表达式中,类似 Python 中可迭代对象的解包行为

不使用 UNPACK 时,对 COLUMNS 表达式的操作会分别应用到每一列:

SELECT coalesce(COLUMNS(['a', 'b', 'c'])) AS result
FROM (SELECT NULL a, 42 b, true c);
resultresultresult
NULL42true

使用 UNPACK 后,COLUMNS 表达式会展开到其父表达式中(上例中为 coalesce),因此结果会变成单列:

SELECT coalesce(UNPACK(COLUMNS(['a', 'b', 'c']))) AS result
FROM (SELECT NULL AS a, 42 AS b, true AS c);
result
42

UNPACK 直接作用于 COLUMNS 表达式且中间没有任何其他操作时,UNPACK 关键字可以替换为 *与 Python 语法一致

SELECT coalesce(*COLUMNS(*)) AS result
FROM (SELECT NULL a, 42 AS b, true AS c);
result
42

警告:在下面的示例中,将 UNPACK 替换为 * 会导致语法错误:

SELECT greatest(UNPACK(COLUMNS(*) + 1)) AS result
FROM (SELECT 1 AS a, 2 AS b, 3 AS c);
result
4

STRUCT.*

* 表达式也可以用于把 struct 中的所有键提取为独立列。 当上一步操作产生了形状未知的 struct,或者查询需要处理 struct 中任意可能出现的键时,这一能力尤其有用。 关于如何使用 struct 的更多细节,请参阅 STRUCT data typeSTRUCT functions 页面。

例如:

SELECT st.* FROM (SELECT {'x': 1, 'y': 2, 'z': 3} AS st);
xyz
123