Informix窗口函数range子句的行为类似于rows子句

时间:2019-03-15 17:47:40

标签: sql informix window-functions

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);

令人惊讶的是,它为rangerows产生了相同的结果:

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对应。

2 个答案:

答案 0 :(得分:1)

这是documented的行为:

  

如果为窗口聚合函数指定了ORDER子句但未指定任何窗口框架子句,则默认情况下,将返回当前行和当前行之前的所有行,这等效于以下窗口框架规范:      

未绑定的行和当前行之间的行

我相信当没有窗口条款存在时,标准是RANGE。我很确定这是大多数其他数据库中的默认设置。

答案 1 :(得分:1)

作为一种解决方法,我可以使用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   |