DuckDB中含空值的重复时序数据高效去重补全方案问询
DuckDB高效合并同时间戳互补空值的时序数据
核心方案:GROUP BY + 忽略NULL的聚合函数
针对同timestamp下各列空值互补的场景,直接按时间戳分组,使用MAX()/MIN()/ANY_VALUE()这类自动忽略NULL的聚合函数,即可高效合并成单条非空记录,完全替代低效的多子查询关联方案。
示例代码
首先创建测试数据:
CREATE TABLE time_series ( timestamp TIMESTAMP, A INT, B VARCHAR ); INSERT INTO time_series VALUES ('2024-01-01 00:00:00', 10, NULL), ('2024-01-01 00:00:00', NULL, 'abc'), ('2024-01-01 00:01:00', 20, NULL), ('2024-01-01 00:01:00', NULL, 'def');
执行合并查询:
SELECT timestamp, MAX(A) AS A, MAX(B) AS B FROM time_series GROUP BY timestamp;
结果输出
┌─────────────────────┬───────┬───────┐ │ timestamp │ A │ B │ │ timestamp │ int32 │ varchar│ ├─────────────────────┼───────┼───────┤ │ 2024-01-01 00:00:00 │ 10 │ abc │ │ 2024-01-01 00:01:00 │ 20 │ def │ └─────────────────────┴───────┴───────┘
方案优势
- 性能高效:DuckDB对聚合查询做了深度优化,向量化执行+并行计算,内存占用远低于关联查询,大数据量下速度媲美甚至超过Pandas。
- 语句简洁:列再多只需在SELECT中依次添加
MAX(列名)即可,不会出现臃肿的关联逻辑。 - 版本兼容:DuckDB v0.10.1原生支持这些聚合函数,无需升级。
备选方案(特殊场景)
如果需要保留原始行的额外属性,可使用窗口函数填充空值后去重:
SELECT DISTINCT timestamp, FIRST_VALUE(A) OVER (PARTITION BY timestamp ORDER BY A IS NULL) AS A, FIRST_VALUE(B) OVER (PARTITION BY timestamp ORDER BY B IS NULL) AS B FROM time_series;
注:此方案效率略低于GROUP BY聚合,仅在特殊需求下使用。
注意点
- 确保同
timestamp下每个列的非空值唯一(符合你的互补空值场景);若存在多个非空值,MAX()取最大值,ANY_VALUE()取任意非空值,可根据业务需求选择聚合函数。
内容的提问来源于stack exchange,提问作者Miguel Farrajota
相关产品推荐
相关产品推荐

