为啥这个框架的默认 OVER () 行为?

Posted

技术标签:

【中文标题】为啥这个框架的默认 OVER () 行为?【英文标题】:Why this default OVER () behavior for the frame?为什么这个框架的默认 OVER () 行为? 【发布时间】:2020-11-24 06:02:11 【问题描述】:

我从以下两个窗口函数中注意到:

WITH sales AS (
    select 2020 as year, 100 as revenue UNION
    select 2021 as year, 200 as revenue UNION
    select 2022 as year, 300 as revenue UNION
    select 2023 as year, 100 as revenue
)
SELECT JSON_ARRAYAGG(revenue) OVER (order by year) FROM sales LIMIT 1;

# revenue_list
[100]

还有这个:

WITH sales AS (
    select 2020 as year, 100 as revenue UNION
    select 2021 as year, 200 as revenue UNION
    select 2022 as year, 300 as revenue UNION
    select 2023 as year, 100 as revenue
)
SELECT JSON_ARRAYAGG(revenue) OVER () revenue_list FROM sales LIMIT 1;
# revenue_list
[100, 200, 300, 100]

框架的默认行为似乎是:

如果没有提供任何东西 -- () -- 那么默认框架是UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING 如果提供了任何东西——(order by year)(partition by year) 等——那么默认框架是UNBOUNDED PRECEDING AND CURRENT ROW

这是对默认框架行为的正确理解吗?如果是这样,为什么会做出这样的选择? (例如,为什么不让它总是无限的,除非用户指定?)

【问题讨论】:

【参考方案1】:

第一个查询中的LIMIT 1 子句会误导您。考虑没有任何LIMIT 子句的完整查询:

SELECT JSON_ARRAYAGG(revenue) OVER (ORDER BY year) FROM sales;

由此生成的结果集是:

[100] 被返回的原因......完全是任意的。您的LIMIT 查询中没有ORDER BY 子句,因此我们在结果集中看到的“第一条”记录恰好被返回(但理论上它可以是任何 四个记录)。

OVER () 版本只会将整个表格呈现为一个 JSON 数组,但会为每条记录显示该值。

SELECT JSON_ARRAYAGG(revenue) OVER () FROM sales;  -- [100, 200, 300, 100] each record
SELECT JSON_ARRAYAGG(revenue) FROM sales;          -- [100, 200, 300, 100] one record

【讨论】:

换句话说,默认帧总是UNBOUNDED PRECEDING AND CURRENT ROW ? 是的,正确的。所以OVER (ORDER BY year)OVER (ORDER BY year ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 相同......但为了简洁起见,我们通常总是只使用前者。

以上是关于为啥这个框架的默认 OVER () 行为?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 XmlReader 中的默认编码与 XmlTextReader 默认编码的行为不同?

e.preventDefault() 阻止默认行为,但不返回 false。为啥?

html5拖拽ondragover为啥要阻止默认行为

EF Core - 为啥 ClientSetNull 是可选关系的默认 OnDelete 行为(而不是 SetNull)

Hive 分析函数lead、lag实例应用

为啥 Java 8 的 Cloneable 中没有默认的 clone()