You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于Window function中ORDER BY子句结合BETWEEN运算符的疑问

窗口函数ORDER BY子句的逻辑解析及结果说明

你的代码中ORDER BY的实际作用

你在ARRAY_AGG窗口函数里写的ORDER BY day BETWEEN '2023-01-02' AND '2023-01-03',完全不是过滤行——它是把布尔表达式的结果作为排序键来排序窗口内的行:

  • 当day在指定范围内时,表达式返回true,SQL会将其转为数值1;不在范围内时返回false,转为数值0。
  • 窗口函数默认按从小到大排序,所以0(对应2023-01-01)的行排在最前面,1(对应2023-01-02、01-03)的行排在后面。

同时,窗口函数在指定ORDER BY但未显式声明窗口框架时,默认采用RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW的框架规则:

  • RANGE会把所有排序键值与当前行相同的行都纳入窗口范围。
  • 所以对于排序键为1的行(2023-01-02和01-03),窗口会包含所有排序键≤1的行(也就是全部三行);排序键为0的行只包含自己。

结果逐行对应逻辑

dayspentss结果逻辑
'2023-01-01'1排序键为0,窗口仅包含自身,聚合结果[1]
'2023-01-02'2排序键为1,窗口包含所有排序键≤1的行(全部三行),聚合结果[1,2,3]
'2023-01-03'3排序键为1,和上一行排序键相同,窗口同样包含全部三行,聚合结果[1,2,3]

为什么和预期不符

你混淆了窗口排序和行过滤的逻辑:想要限制聚合的行范围,不能把过滤条件放在ORDER BY子句里,而是要用正确的过滤方式。

比如,如果你想让每一行的ss都只包含指定日期范围内的spent值,可以用FILTER子句:

WITH samp AS (
    SELECT '2023-01-01' AS day, 1 AS spent UNION ALL
    SELECT '2023-01-02' AS day, 2 AS spent UNION ALL 
    SELECT '2023-01-03' AS day, 3 AS spent
) 
SELECT day, 
       spent 
     , ARRAY_AGG(spent) FILTER (WHERE day BETWEEN '2023-01-02' AND '2023-01-03') OVER() ss
FROM samp 
ORDER BY day

执行后所有行的ss都会是[2,3]。

如果是想要实现滑动窗口(仅聚合当前行及之前的指定日期数据),则需要显式定义窗口框架(不同SQL方言语法略有差异,以你的使用环境为准)。

内容的提问来源于stack exchange,提问作者simon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 03:45:01