在Informix中考虑以下语句:
SELECT
a,
b,
sum(a) over (order by b) "no frame",
sum(a) over (order by b range between unbounded preceding and current row) "range",
sum(a) over (order by b rows between unbounded preceding and current row) "rows"
FROM TABLE(SET{row(1, 1), row(2, 1), row(3, 2), row(4, 2)}) AS t(a, b);
令人惊讶的是,它为range
和rows
产生了相同的结果:
a |b |no frame |range |rows |
--|--|---------|------|-----|
1 |1 |3 |1 |1 |
2 |1 |3 |3 |3 |
3 |2 |10 |6 |6 |
4 |2 |10 |10 |10 |
这与我以前使用的任何RDBMS完全不同,包括PostgreSQL:
SELECT
a,
b,
sum(a) over (order by b) "no frame",
sum(a) over (order by b range between unbounded preceding and current row) "range",
sum(a) over (order by b rows between unbounded preceding and current row) "rows"
FROM (values(1, 1), (2, 1), (3, 2), (4, 2)) AS t(a, b);
...产生预期的
a |b |no frame |range |rows |
--|--|---------|------|-----|
1 |1 |3 |3 |1 |
2 |1 |3 |3 |3 |
3 |2 |10 |10 |6 |
4 |2 |10 |10 |10 |
我错过了Informix和标准SQL之间的细微差别,还是一个bug?我正在使用official docker image,它对应于现在的Informix 12.10。
这是documented行为:
如果为窗口聚合函数指定ORDER子句但没有窗口框子句,则默认情况下,返回当前行和当前行之前的所有行,这等同于以下窗口框架规范:
无界前进与当前行之间的行程
我认为当没有窗口条款时,标准是RANGE
。我很确定这是大多数其他数据库的默认设置。
作为一种解决方法,我可以使用0 PRECEDING
(不应该允许,但很好)而不是CURRENT ROW
。这产生了我预期的结果:
SELECT
a,
b,
sum(a) over (order by b) "no frame",
sum(a) over (order by b range between unbounded preceding and 0 preceding) "range",
sum(a) over (order by b rows between unbounded preceding and current row) "rows"
FROM (values(1, 1), (2, 1), (3, 2), (4, 2)) AS t(a, b);
我现在得到:
a |b |no frame |range |rows |
--|--|---------|------|-----|
1 |1 |3 |3 |1 |
2 |1 |3 |3 |3 |
3 |2 |10 |10 |6 |
4 |2 |10 |10 |10 |