DuckDB 提供了几种高级 SQL 功能和语法糖,以使 SQL 查询更加简洁。我们通常将这些称为“友好的 SQL”。
这些特性中的一些在其他系统中也得到支持,而有些(目前)是DuckDB独有的。
Clauses
- 创建表和插入数据:
CREATE OR REPLACE TABLE: 避免在脚本中使用DROP TABLE IF EXISTS语句。CREATE TABLE ... AS SELECT(CTAS): 从表的输出中创建一个新表,而无需手动定义模式。INSERT INTO ... BY NAME: 这种INSERT语句的变体允许使用列名而不是位置。INSERT OR IGNORE INTO ...: 插入不会因UNIQUE或PRIMARY KEY约束而导致冲突的行。INSERT OR REPLACE INTO ...: 插入不会因UNIQUE或PRIMARY KEY约束而导致冲突的行。对于导致冲突的行,将现有行的列替换为要插入行的新值。
- 描述表和计算统计信息:
- 使SQL子句更紧凑:
FROM-first syntax with an optionalSELECTclause: DuckDB允许以FROM tbl形式进行查询,选择所有列(执行SELECT *语句)。GROUP BY ALL: 通过从SELECT子句中的属性列表推断分组列,省略分组列。ORDER BY ALL: 对所有列进行排序的简写(例如,确保确定性结果)。SELECT * EXCLUDE:EXCLUDE选项允许从*表达式中排除特定列。SELECT * REPLACE:REPLACE选项允许在*表达式中用不同的表达式替换特定列。UNION BY NAME: 根据列名执行UNION操作(而不是依赖位置)。
- 转换表格:
- 定义SQL级别的变量:
查询功能
- 在
WHERE、GROUP BY和HAVING中的列别名。(请注意,列别名不能在JOIN子句的ON子句中使用。) COLUMNS()表达式 可以用于在多个列上执行相同的表达式:- 可重复使用的列别名,例如:
SELECT i + 1 AS j, j + 2 AS k FROM range(0, 3) t(i) - 用于分析(OLAP)查询的高级聚合功能:
count()简写 用于count(*)
字面量和标识符
Data Types
Data Import
- 自动检测CSV文件的标题和模式
- 直接查询 CSV 文件 和 Parquet 文件
- 使用语法
FROM 'my.csv',FROM 'my.csv.gz',FROM 'my.parquet'等从文件加载。 - 文件名扩展(globbing), 例如:
FROM 'my-data/part-*.parquet'
函数和表达式
- 用于函数链的点操作符:
SELECT ('hello').upper() - 字符串格式化器:
format()函数与fmt语法 和printf() 函数 - 列表推导式
- 列表切片
- 字符串切片
STRUCT.*表示法- 简单的
LIST和STRUCT创建
连接类型
尾随逗号
DuckDB 允许在列出实体(例如列名和表名)以及构建 LIST 项 时使用 尾随逗号。
例如,以下查询有效:
SELECT
42 AS x,
['a', 'b', 'c',] AS y,
'hello world' AS z,
;
"Top-N in Group" 查询
在SQL中,按某些标准计算“组中的前N行”是一个常见任务,不幸的是,这通常需要一个涉及窗口函数和/或子查询的复杂查询。
为了帮助实现这一点,DuckDB 提供了聚合函数 max(arg, n), min(arg, n), arg_max(arg, val, n), arg_min(arg, val, n), max_by(arg, val, n) 和 min_by(arg, val, n),以高效地返回基于特定列的升序或降序排列的组中的“前”n行。
例如,我们使用以下表格:
SELECT * FROM t1;
┌─────────┬───────┐
│ grp │ val │
│ varchar │ int32 │
├─────────┼───────┤
│ a │ 2 │
│ a │ 1 │
│ b │ 5 │
│ b │ 4 │
│ a │ 3 │
│ b │ 6 │
└─────────┴───────┘
我们想要获取每个组grp中前3个val值的列表。传统的方法是在子查询中使用窗口函数:
SELECT array_agg(rs.val), rs.grp
FROM
(SELECT val, grp, row_number() OVER (PARTITION BY grp ORDER BY val DESC) AS rid
FROM t1 ORDER BY val DESC) AS rs
WHERE rid < 4
GROUP BY rs.grp;
┌───────────────────┬─────────┐
│ array_agg(rs.val) │ grp │
│ int32[] │ varchar │
├───────────────────┼─────────┤
│ [3, 2, 1] │ a │
│ [6, 5, 4] │ b │
└───────────────────┴─────────┘
但在DuckDB中,我们可以更简洁(且高效!)地完成这个操作:
SELECT max(val, 3) FROM t1 GROUP BY grp;
┌─────────────┐
│ max(val, 3) │
│ int32[] │
├─────────────┤
│ [3, 2, 1] │
│ [6, 5, 4] │
└─────────────┘