真实用toStartOfInterval做5分钟时间分桶,故意制造数据缺口,对比有无WITH FILL时缺失时间点在结果里的真实呈现方式。
代码CREATE TABLE demo.tsdata (ts DateTime, v Float64) ENGINE=MergeTree ORDER BY ts; INSERT INTO demo.tsdata SELECT toDateTime('2026-01-01 00:00:00')+number*37, sin(number/50)*10+20 FROM numbers(100000); SELECT toStartOfInterval(ts, INTERVAL 5 MINUTE) AS bucket, avg(v) FROM demo.tsdata GROUP BY bucket; -- 真实删掉一段时间的数据,制造缺口 ALTER TABLE demo.tsdata DELETE WHERE ts >= '2026-01-01 00:10:00' AND ts < '2026-01-01 00:20:00';
SELECT toStartOfInterval(ts,INTERVAL 5 MINUTE) AS bucket, avg(v) FROM demo.tsdata WHERE ts<'2026-01-01 00:30:00' GROUP BY bucket ORDER BY bucket; → 00:00:00 20.80 00:05:00 22.47 00:20:00 26.66 ← 真实直接跳到了00:20,00:10和00:15两个桶消失了 00:25:00 27.76
普通的GROUP BY只会真实输出数据里真的存在的分组,00:10和00:15这两个桶因为数据被真实删掉了,压根不会出现在结果里——如果下游要拿这份结果画一张连续的时序图,真实会在图上留下一个视觉上的"跳跃",容易被误读成横轴间隔不均匀。
... GROUP BY bucket ORDER BY bucket
WITH FILL FROM toDateTime('2026-01-01 00:00:00') TO toDateTime('2026-01-01 00:30:00')
STEP INTERVAL 5 MINUTE;
→ 00:00:00 20.80
00:05:00 22.47
00:10:00 0 ← 真实被WITH FILL补齐了,但avg(v)的值真实是0,不是插值
00:15:00 0 ← 同样是0
00:20:00 26.66
00:25:00 27.76每一步都是本文上面用真实时序数据跑出来的原始结果。
toStartOfInterval 与 WITH FILL