Examples
选择FROM子句中存在的所有列:
SELECT * FROM table_name;
计算表中的行数:
SELECT count(*) FROM table_name;
DuckDB 为 count(*) 表达式提供了一种简写形式,其中 * 可以省略:
SELECT count() FROM table_name;
从名为 table_name 的表中选择所有列:
SELECT table_name.*
FROM table_name
JOIN other_table_name USING (id);
从地址表中选择除城市列之外的所有列:
SELECT * EXCLUDE (city)
FROM addresses;
从地址表中选择所有列,但将城市替换为 lower(city):
SELECT * REPLACE (lower(city) AS city)
FROM addresses;
选择所有匹配给定表达式的列:
SELECT COLUMNS(c -> c LIKE '%num%')
FROM addresses;
从表中选择所有匹配给定正则表达式的列:
SELECT COLUMNS('number\d+')
FROM addresses;
使用列表选择列:
SELECT COLUMNS(['city', 'zip_code'])
FROM addresses;
Syntax
Star Expression
* 表达式可以在 SELECT 语句中使用,以选择在 FROM 子句中投影的所有列。
SELECT *
FROM tbl;
* 表达式可以使用 EXCLUDE 和 REPLACE 进行修改。
EXCLUDE 子句
EXCLUDE 允许我们从 * 表达式中排除特定的列。
SELECT * EXCLUDE (col)
FROM tbl;
REPLACE 子句
REPLACE 允许我们根据表达式替换列中的特定值。
SELECT * REPLACE (col / 1_000 AS 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;
| 编号 | 数字 | 编号 | 数字 |
|---|---|---|---|
| 1 | 10 | 3 | 2 |
COLUMNS 语句中的 * 表达式也可以包含 EXCLUDE 或 REPLACE,类似于常规的星号表达式。
SELECT
min(COLUMNS(* REPLACE (number + id AS number))),
count(COLUMNS(* EXCLUDE (number)))
FROM numbers;
| id | min(number := (number + id)) | id |
|---|---|---|
| 1 | 11 | 3 |
COLUMNS 表达式也可以组合使用,只要 COLUMNS 包含相同的(星号)表达式:
SELECT COLUMNS(*) + COLUMNS(*) FROM numbers;
| 编号 | 数字 |
|---|---|
| 2 | 20 |
| 4 | 40 |
| 6 | NULL |
COLUMNS 表达式也可以用在 WHERE 子句中。条件会应用于所有列,并使用逻辑 AND 运算符进行组合。
SELECT *
FROM (
SELECT 0 AS x, 1 AS y, 2 AS z
UNION ALL
SELECT 1 AS x, 2 AS y, 3 AS z
UNION ALL
SELECT 2 AS x, 3 AS y, 4 AS z
)
WHERE COLUMNS(*) > 1; -- equivalent to: x > 1 AND y > 1 AND z > 1
| x | y | z |
|---|---|---|
| 2 | 3 | 4 |
COLUMNS 正则表达式
COLUMNS 支持将正则表达式作为字符串常量传递:
SELECT COLUMNS('(id|numbers?)') FROM numbers;
| 编号 | 数字 |
|---|---|
| 1 | 10 |
| 2 | 20 |
| 3 | NULL |
使用COLUMNS表达式重命名列
捕获组的匹配项可用于重命名通过正则表达式选择的列。
捕获组是从1开始索引的;\0 是原始列名。
例如,要选择列名的前三个字母,请运行:
SELECT COLUMNS('(\w{3}).*') AS '\1' FROM numbers;
| id | num |
|---|---|
| 1 | 10 |
| 2 | 20 |
| 3 | NULL |
要删除列名中间的冒号(:)字符,请运行:
CREATE TABLE tbl ("Foo:Bar" INTEGER, "Foo:Baz" INTEGER, "Foo:Qux" INTEGER);
SELECT COLUMNS('(\w*):(\w*)') AS '\1\2' FROM tbl;
COLUMNS Lambda 函数
COLUMNS 还支持传入一个 lambda 函数。该 lambda 函数将对 FROM 子句中存在的所有列进行评估,只有符合 lambda 函数的列才会被返回。这允许执行任意表达式以选择和重命名列。
SELECT COLUMNS(c -> c LIKE '%num%') FROM numbers;
| 数字 |
|---|
| 10 |
| 20 |
| NULL |
*COLUMNS 解包列
*COLUMNS 子句是 COLUMNS 的一种变体,它支持所有前面提到的功能。
区别在于表达式的扩展方式。
*COLUMNS 将会在原地展开,类似于 Python 中的可迭代对象解包行为,这启发了 * 语法的使用。
这意味着表达式会展开到父表达式中。
以下是一个展示 COLUMNS 和 *COLUMNS 之间区别的示例:
使用 COLUMNS:
SELECT coalesce(COLUMNS(['a', 'b', 'c'])) AS result
FROM (SELECT NULL a, 42 b, true c);
| 结果 | 结果 | 结果 |
|---|---|---|
| NULL | 42 | true |
使用*COLUMNS时,表达式在其父表达式coalesce中展开,从而生成一个单一的结果列:
SELECT coalesce(*COLUMNS(['a', 'b', 'c'])) AS result
FROM (SELECT NULL AS a, 42 AS b, true AS c);
| result |
|---|
| 42 |
*COLUMNS 也可以与 (*) 参数一起使用:
SELECT coalesce(*COLUMNS(*)) AS result
FROM (SELECT NULL a, 42 AS b, true AS c);
| result |
|---|
| 42 |
STRUCT.*
* 表达式也可以用于从结构体中检索所有键作为单独的列。
这在先前的操作创建了一个未知形状的结构体,或者查询必须处理任何潜在的结构体键时特别有用。
有关处理结构体的更多详细信息,请参阅 STRUCT 数据类型 和 STRUCT 函数 页面。
例如:
SELECT st.* FROM (SELECT {'x': 1, 'y': 2, 'z': 3} AS st);
| x | y | z |
|---|---|---|
| 1 | 2 | 3 |