命名窗口
分析函数的 OVER
子句可以引用命名窗口,此窗口封装了一个或多个窗口子句:窗口分区 (PARTITION BY
) 子句和(可选)窗口顺序 (ORDER BY
) 子句。编写通过类似的 OVER
子句语法调用多个分析函数的查询时,例如,它们使用相同的分区子句,则命名窗口非常有用。
查询按如下方式命名窗口:
WINDOW window‑name AS ( window-partition-clause [window-order-clause] );
同一个查询可以命名和引用多个窗口。在同一个查询中,所有窗口名称都必须是唯一的。
示例
以下查询调用了两个分析函数,即
RANK
和
DENSE_RANK
。因为两个函数使用同一个分区和顺序子句,查询对指定这两个子句的 w
窗口进行了命名。两个函数引用了此窗口,如下所示:
=> SELECT employee_region region, employee_key, annual_salary,
RANK() OVER w Rank,
DENSE_RANK() OVER w "Dense Rank"
FROM employee_dimension WINDOW w AS (PARTITION BY employee_region ORDER BY annual_salary);
region | employee_key | annual_salary | Rank | Dense Rank
----------------------------------+--------------+---------------+------+------------
West | 5248 | 1200 | 1 | 1
West | 6880 | 1204 | 2 | 2
West | 5700 | 1214 | 3 | 3
West | 9857 | 1218 | 4 | 4
West | 6014 | 1218 | 4 | 4
West | 9221 | 1220 | 6 | 5
West | 7646 | 1222 | 7 | 6
West | 6621 | 1222 | 7 | 6
West | 6488 | 1224 | 9 | 7
West | 7659 | 1226 | 10 | 8
West | 7432 | 1226 | 10 | 8
West | 9905 | 1226 | 10 | 8
West | 9021 | 1228 | 13 | 9
West | 7855 | 1228 | 13 | 9
West | 7119 | 1230 | 15 | 10
...
如果命名窗口忽略了顺序子句,查询的 OVER
子句可以指定自己的顺序子句。例如,您可以修改上一个查询,让每个函数使用不同的顺序子句。命名窗口在定义后仅包括一个分区子句:
=> SELECT employee_region region, employee_key, annual_salary,
RANK() OVER (w ORDER BY annual_salary DESC) Rank,
DENSE_RANK() OVER (w ORDER BY annual_salary ASC) "Dense Rank"
FROM employee_dimension WINDOW w AS (PARTITION BY employee_region);
region | employee_key | annual_salary | Rank | Dense Rank
----------------------------------+--------------+---------------+------+------------
West | 5248 | 1200 | 2795 | 1
West | 6880 | 1204 | 2794 | 2
West | 5700 | 1214 | 2793 | 3
West | 6014 | 1218 | 2791 | 4
West | 9857 | 1218 | 2791 | 4
West | 9221 | 1220 | 2790 | 5
West | 6621 | 1222 | 2788 | 6
West | 7646 | 1222 | 2788 | 6
West | 6488 | 1224 | 2787 | 7
West | 7432 | 1226 | 2784 | 8
West | 9905 | 1226 | 2784 | 8
West | 7659 | 1226 | 2784 | 8
West | 7855 | 1228 | 2782 | 9
West | 9021 | 1228 | 2782 | 9
West | 7119 | 1230 | 2781 | 10
...
同样地,如果命名窗口包含一个顺序子句,OVER
子句可指定命名窗口也指定一个窗口框架子句。如果无法将命名窗口定义为包含一个窗口框架子句,上述用法会非常有用。
例如,以下查询定义了一个封装分区和顺序子句的窗口。OVER
子句调用此窗口,还包含一个窗口框架子句:
=> SELECT deptno, sal, empno, COUNT(*) OVER (w ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS count
FROM emp WINDOW w AS (PARTITION BY deptno ORDER BY sal);
deptno | sal | empno | count
--------+-----+-------+-------
10 | 101 | 1 | 1
10 | 104 | 4 | 2
20 | 100 | 11 | 1
20 | 109 | 8 | 2
20 | 109 | 6 | 3
20 | 109 | 7 | 3
20 | 110 | 10 | 3
20 | 110 | 9 | 3
30 | 102 | 2 | 1
30 | 103 | 3 | 2
30 | 105 | 5 | 3
(11 rows)
递归窗口引用
WINDOW
子句可引用另一个已经命名的窗口。例如,由于命名窗口 w1
是在 w2
之前定义的,因此定义 w2
的 WINDOW
子句可以引用 w1
:
=> SELECT RANK() OVER(w1 ORDER BY sal DESC), RANK() OVER w2
FROM EMP WINDOW w1 AS (PARTITION BY deptno), w2 AS (w1 ORDER BY sal);
限制
-
OVER
子句只能引用一个命名窗口。 -
同一个查询中的每个
WINDOW
子句都必须拥有唯一的名称。