【Spark】默认的 window frame

SQL 窗口函数经常使用, 但是在修改历史代码时会经常忽略掉一些隐蔽的默认行为,
使得代码留下 bug, 比如下面两个结果是一样的吗:

sum(..) over(partition by dimension_1)
sum(..) over(partition by dimension_1 order by metric_1)

答案是不一样的. 为什么呢? 这就要翻出 window frame 的完整定义.

window frame 的完整定义

over() 语法定义:

window_function_name(expression) 
OVER (
[partition_defintion]
[order_definition]
[frame_definition]
)

当我们使用 over(partition by dimension_1) 时, 默认省略了一些东西,
那就是默认的 [frame_definition] 这部分, 也就是下面的
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.

而当我们同时使用了 order by 之后, [frame_definition] 将会采用下面的 [frame_definition] :
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.

首先因为 UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING 表示将会计算整个 partition by dimension_1 的数据范围,
然而 UNBOUNDED PRECEDING AND CURRENT ROW 只会计算 partition by dimension_1 排序后第一行到 CURRENT ROW 当前行的数据.

因此, 两者的结果是不同的.

默认的行为往往是产生 bug 的地方, 即使懂得也容易疏忽.

参考

https://stackoverflow.com/questions/47130030/whats-the-default-window-frame-for-window-functions