ROWS和RANGE
功能描述
ROWS
和RANGE
关键字为每一行定义一个窗口(一组物理或逻辑行),用于计算函数结果,然后将该函数应用于窗口中的所有行。窗口从上到下在查询结果集或分区中移动。
- ROWS窗口由物理行构成。
- RANGE窗口由逻辑偏移量构成。
- 若完全忽略
opt_win_range
,则默认的窗口范围为RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
。
窗口计算规则
ROWS
Window|ASC/DESC | ASC窗口计算规则 | DESC窗口计算规则 |
---|---|---|
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING | 窗口开始于分组第一行,结束于分组最后一行 | 同ASC一致 |
ROWS [BETWEEN] UNBOUNDED PRECEDING [AND CURRENT ROW] | 窗口开始于分组第一行,结束于当前行 | 同ASC一致 |
ROWS BETWEEN UNBOUNDED PRECEDING AND value_expr PRECEDING | 窗口开始于分组第一行,结束于当前行前value_expr行 | 同ASC一致 |
ROWS BETWEEN UNBOUNDED PRECEDING AND value_expr FOLLOWING | 窗口开始于分组第一行,结束于当前行后value_expr行 | 同ASC一致 |
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING | 窗口开始于当前行,结束于分组最后一行 | 同ASC一致 |
ROWS [BETWEEN CURRENT ROW AND] CURRENT ROW | 窗口开始于当前行,结束于当前行 | 同ASC一致 |
ROWS BETWEEN CURRENT ROW AND value_expr FOLLOWING | 窗口开始于当前行,结束于当前行后value_expr行 | 同ASC一致 |
ROWS BETWEEN value_expr PRECEDING AND UNBOUNDED FOLLOWING | 窗口开始于当前行前value_expr行,结束于分组最后一行 | 同ASC一致 |
ROWS [BETWEEN value_expr] PRECEDING [AND CURRENT ROW] | 窗口开始于当前行前value_expr行,结束于当前行 | 同ASC一致 |
ROWS BETWEEN value_expr1 PRECEDING AND value_expr2 PRECEDING | 窗口开始于当前行前value_expr1行,结束于当前行前value_expr2行 | 同ASC一致 |
ROWS BETWEEN value_expr1 PRECEDING AND value_expr2 FOLLOWING | 窗口开始于当前行前value_expr1行,结束于当前行后value_expr2行 | 同ASC一致 |
ROWS BETWEEN value_expr FOLLOWING AND UNBOUNDED FOLLOWING | 窗口开始于当前行后value_expr行,结束于分组最后一行 | 同ASC一致 |
ROWS BETWEEN value_expr1 FOLLOWING AND value_expr2 FOLLOWING | 窗口开始于当前行后value_expr1行,结束于当前行后value_expr2行 | 同ASC一致 |
ROWS UNBOUNDED PRECEDING | 窗口开始于分组第一行,结束于当前行 | 同ASC一致 |
ROWS CURRENT ROW | 窗口开始于当前行,结束于当前行 | 同ASC一致 |
ROWS value_expr PRECEDING | 窗口开始于当前行前value_expr行,结束于当前行 | 同ASC一致 |
ROWS BETWEEN CURRENT ROW AND value_expr PRECEDING | 无效 | 无效 |
ROWS BETWEEN value_expr FOLLOWING AND CURRENT ROW | 无效 | 无效 |
ROWS BETWEEN value_expr1 FOLLOWING AND value_expr2 PRECEDING | 无效 | 无效 |
ROWS UNBOUNDED FOLLOWING | 无效 | 无效 |
ROWS value_expr FOLLOWING | 无效 | 无效 |
RANGE
Window|ASC/DESC | ASC窗口计算规则 | DESC窗口计算规则 |
---|---|---|
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING | WHERE expr BETWEEN first_value AND last_value | WHERE expr BETWEEN last_value AND first_value |
RANGE [BETWEEN] UNBOUNDED PRECEDING [AND CURRENT ROW] | WHERE expr BETWEEN first_value AND current_value | WHERE expr BETWEEN current_value AND first_value |
RANGE BETWEEN UNBOUNDED PRECEDING AND value_expr PRECEDING | WHERE expr BETWEEN first_value AND current_value-value_expr | WHERE expr BETWEEN current_value+value_expr AND first_value |
RANGE BETWEEN UNBOUNDED PRECEDING AND value_expr FOLLOWING | WHERE expr BETWEEN first_value AND current_value+value_expr | WHERE expr BETWEEN current_value-value_expr AND first_value |
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING | WHERE expr BETWEEN current_value AND last_value | WHERE expr BETWEEN last_value AND current_value |
RANGE [BETWEEN CURRENT ROW AND] CURRENT ROW | WHERE expr = current_value | WHERE expr = current_value |
RANGE BETWEEN CURRENT ROW AND value_expr FOLLOWING | WHERE expr BETWEEN current_value AND current_value+value_expr | WHERE expr BETWEEN current_value-value_expr AND current_value |
RANGE BETWEEN value_expr PRECEDING AND UNBOUNDED FOLLOWING | WHERE expr BETWEEN current_value-value_expr AND last_value | WHERE expr BETWEEN last_value AND current_value+value_expr |
RANGE [BETWEEN value_expr] PRECEDING [AND CURRENT ROW] | WHERE expr BETWEEN current_value-value_expr AND current_value | WHERE expr BETWEEN current_value AND current_value+value_expr |
RANGE BETWEEN value_expr1 PRECEDING AND value_expr2 PRECEDING | WHERE expr BETWEEN current_value-value_expr1 AND current_value-value_expr2 | WHERE expr BETWEEN current_value+value_expr2 AND current_value+value_expr1 |
RANGE BETWEEN value_expr1 PRECEDING AND value_expr2 FOLLOWING | WHERE expr BETWEEN current_value-value_expr1 AND current_value+value_expr2 | WHERE expr BETWEEN current_value-value_expr2 AND current_value+value_expr1 |
RANGE BETWEEN value_expr FOLLOWING AND UNBOUNDED FOLLOWING | WHERE expr BETWEEN current_value+value_expr AND last_value | WHERE expr BETWEEN last_value AND current_value-value_expr |
RANGE BETWEEN value_expr1 FOLLOWING AND value_expr2 FOLLOWING | WHERE expr BETWEEN current_value+value_expr1 AND current_value+value_expr2 | WHERE expr BETWEEN current_value-value_expr2 AND current_value-value_expr1 |
RANGE UNBOUNDED PRECEDING (与RANGE [BETWEEN] UNBOUNDED PRECEDING [AND CURRENT ROW]等价) | WHERE expr BETWEEN first_value AND current_value | WHERE expr BETWEEN current_value AND first_value |
RANGE CURRENT ROW (与RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING等价) | WHERE expr = current_value | WHERE expr = current_value |
RANGE value_expr PRECEDING (与RANGE [BETWEEN value_expr] PRECEDING [AND CURRENT ROW]等价) | WHERE expr BETWEEN current_value-value_expr AND current_value | WHERE expr BETWEEN current_value AND current_value+value_expr |
RANGE BETWEEN CURRENT ROW AND value_expr PRECEDING | 无效 | 无效 |
RANGE BETWEEN value_expr FOLLOWING AND CURRENT ROW | 无效 | 无效 |
RANGE BETWEEN value_expr1 FOLLOWING AND value_expr2 PRECEDING | 无效 | 无效 |
RANGE UNBOUNDED FOLLOWING | 无效 | 无效 |
RANGE value_expr FOLLOWING | 无效 | 无效 |
ORDER BY排序为单字段
相当于给opt_win_order
中的expr
加WHERE
限定条件,即WHERE expr BETWEEN a AND b
构成了一个逻辑窗口,此窗口在expr
包含的行上滑动求值。a
和b
的值可结合opt_win_range
窗口求值确定。order_by_clause
子句为ASC
和DESC
,a
和b
的求值可能有所不同。
假设分组排序后第一行的值为first_value
,最后一行的值为last_value
,当前行的值为current_value
:
UNBOUNDED PRECEDING
=first_value
UNBOUNDED FOLLOWING
=last_value
CURRENT ROW
=current_value
value_expr PRECEDING
=current_value
-/+value_expr
value_expr FOLLOWING
=current_value
+/-value_expr
说明:
若排序指定
DESC
。
- 窗口为
value_expr PRECEDING
则current_value + value_expr
。- 窗口为
value_expr FOLLOWING
则current_value - value_expr
。
ORDER BY排序为多字段
仅允许下述开窗。
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
RANGE BETWEEN CURRENT ROW AND CURRENT ROW
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED
示例
ROWS
sql
SQL> CREATE TABLE over_test(name VARCHAR(20),age INT);
SQL> INSERT INTO over_test VALUES('a',15)('e',10)('f',21)('c',15)('d',9)('b',9);
SQL> SELECT name,age,COUNT(age) OVER(PARTITION BY age ORDER BY age ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM over_test ORDER BY age;
NAME | AGE | EXPR1 |
------------------------------------------------------------------------------
b| 9 | 2 |
d| 9 | 1 |
e| 10 | 1 |
c| 15 | 2 |
a| 15 | 1 |
f| 21 | 1 |
RANGE
sql
SQL> SELECT name,age,COUNT(age) OVER(PARTITION BY age ORDER BY age RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) FROM over_test ORDER BY age;
NAME | AGE | EXPR1 |
------------------------------------------------------------------------------
b| 9 | 2 |
d| 9 | 2 |
e| 10 | 1 |
c| 15 | 2 |
a| 15 | 2 |
f| 21 | 1 |