可以通过在 OVER
子句中引用它们的名称来定义窗口并为其命名。为此,请使用 WINDOW
子句。如果查询中存在 WINDOW
子句,则它位于 HAVING
和 ORDER BY
子句之间,并具有以下语法:
WINDOW window_name AS (window_spec)
[, window_name AS (window_spec)] ...
对于每个窗口定义,window_name
是窗口名称,window_spec
是与 OVER
子句括号之间给出的窗口规范相同的类型,如 第 14.20.2 节“窗口函数概念和语法” 中所述。
window_spec:
[window_name] [partition_clause] [order_clause] [frame_clause]
当多个 OVER
子句需要定义相同的窗口时,WINDOW
子句很有用。您可以定义一次窗口,为其命名,然后在 OVER
子句中引用该名称。请考虑以下查询,它多次定义了相同的窗口:
SELECT
val,
ROW_NUMBER() OVER (ORDER BY val) AS 'row_number',
RANK() OVER (ORDER BY val) AS 'rank',
DENSE_RANK() OVER (ORDER BY val) AS 'dense_rank'
FROM numbers;
可以通过使用 WINDOW
定义一次窗口并在 OVER
子句中按名称引用该窗口来更简单地编写查询:
SELECT
val,
ROW_NUMBER() OVER w AS 'row_number',
RANK() OVER w AS 'rank',
DENSE_RANK() OVER w AS 'dense_rank'
FROM numbers
WINDOW w AS (ORDER BY val);
命名窗口还可以更轻松地尝试使用窗口定义来查看对查询结果的影响。您只需修改 WINDOW
子句中的窗口定义,而无需修改多个 OVER
子句定义。
如果 OVER
子句使用 OVER (
而不是 window_name
...)OVER
,则可以通过添加其他子句来修改命名窗口。例如,以下查询定义了一个包含分区的窗口,并在 window_name
OVER
子句中使用 ORDER BY
以不同的方式修改窗口:
SELECT
DISTINCT year, country,
FIRST_VALUE(year) OVER (w ORDER BY year ASC) AS first,
FIRST_VALUE(year) OVER (w ORDER BY year DESC) AS last
FROM sales
WINDOW w AS (PARTITION BY country);
OVER
子句只能向命名窗口添加属性,而不能修改它们。如果命名窗口定义包含分区、排序或框架属性,则引用该窗口名称的 OVER
子句不能同时包含相同类型的属性,否则会发生错误。
允许使用此构造,因为窗口定义和引用的
OVER
子句不包含相同类型的属性。OVER (w ORDER BY country) ... WINDOW w AS (PARTITION BY country)
不允许使用此构造,因为
OVER
子句为已具有PARTITION BY
的命名窗口指定了PARTITION BY
。OVER (w PARTITION BY year) ... WINDOW w AS (PARTITION BY country)
命名窗口的定义本身可以以 window_name
开头。在这种情况下,允许前向和后向引用,但不允许循环。
这是允许的;它包含前向和后向引用,但没有循环。
WINDOW w1 AS (w2), w2 AS (), w3 AS (w1)
这是不允许的,因为它包含一个循环。
WINDOW w1 AS (w2), w2 AS (w3), w3 AS (w1)