对于许多操作,DuckDB保留了行的顺序,类似于Pandas等数据框库。
Example
以下表为例:
CREATE TABLE tbl AS
SELECT *
FROM (VALUES (1, 'a'), (2, 'b'), (3, 'c')) t(x, y);
SELECT *
FROM tbl;
x | y |
---|---|
1 | a |
2 | b |
3 | c |
让我们来看以下查询,它返回x
为奇数的行:
SELECT *
FROM tbl
WHERE x % 2 == 1;
x | y |
---|---|
1 | a |
3 | c |
因为行 (1, 'a')
在原表中出现在 (3, 'c')
之前,所以在这个表中也保证会出现在该行之前。
Clauses
以下子句保证原始行顺序得以保留:
COPY
(参见 插入顺序)FROM
使用单个表LIMIT
OFFSET
SELECT
UNION ALL
WHERE
- 带有空
OVER
子句的窗口函数 - 只要它们仅包含上述组件,公共表表达式和表子查询
提示
row_number() OVER ()
允许将原始行顺序转换为一个显式列,可以在默认不保留行顺序的操作中引用。在物化表上,可以使用rowid
伪列达到相同的效果。
以下操作不保证行顺序被保留:
FROM
带有多个表和/或子查询JOIN
UNION
USING SAMPLE
GROUP BY
(特别是,输出顺序是未定义的,并且除非在聚合函数中明确指定,否则行被输入到order-sensitive aggregate functions的顺序也是未定义的)ORDER BY
(特别是,ORDER BY
可能不会使用 稳定算法)- 标量子查询
插入顺序
默认情况下,以下组件保留插入顺序:
- CSV 读取器 (
read_csv
函数) - JSON 阅读器 (
read_json
函数) - Parquet 读取器 (
read_parquet
函数)
插入顺序的保留由preserve_insertion_order
配置选项控制。
此设置默认为true
,表示应保留顺序。
要更改此设置,请使用:
SET preserve_insertion_order = false;