Documentation Home

12.21.4 命名窗口

可以定义窗口并为其指定名称,以便在OVER子句中引用它们。为此,请使用 WINDOW子句。如果出现在查询中,则该 WINDOW子句位于HAVINGORDER BY 子句的位置之间,并具有以下语法:

Press CTRL+C to copy
WINDOW window_name AS (window_spec) [, window_name AS (window_spec)] ...

对于每个窗口定义, window_name是窗口名称,并且 window_specOVER子句括号之间给出的相同类型的窗口规范,如 第 12.21.2 节,“窗口函数概念和语法”中所述:

Press CTRL+C to copy
window_spec: [window_name] [partition_clause] [order_clause] [frame_clause]

子句对于多个子句将以其他方式定义同一窗口WINDOW的查询很有用。相反,您可以定义窗口一次,给它一个名称,然后在子句OVER中引用该名称 。OVER考虑这个查询,它多次定义同一个窗口:

Press CTRL+C to copy
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

Press CTRL+C to copy
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子句使用rather than ,则可以通过添加其他子句来修改命名窗口。例如,此查询定义了一个包含分区的窗口,并在 子句中使用以不同方式修改窗口: OVER (window_name ...)OVER window_nameORDER BYOVER

Press CTRL+C to copy
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子句不包含相同类型的属性:

    Press CTRL+C to copy
    OVER (w ORDER BY country) ... WINDOW w AS (PARTITION BY country)
  • 不允许使用此构造,因为该 OVER子句指定PARTITION BY了一个已具有的命名窗口 PARTITION BY

    Press CTRL+C to copy
    OVER (w PARTITION BY year) ... WINDOW w AS (PARTITION BY country)

命名窗口的定义本身可以以 window_name. 在这种情况下,允许向前和向后引用,但不允许循环:

  • 这是允许的;它包含向前和向后引用但没有循环:

    Press CTRL+C to copy
    WINDOW w1 AS (w2), w2 AS (), w3 AS (w1)
  • 这是不允许的,因为它包含一个循环:

    Press CTRL+C to copy
    WINDOW w1 AS (w2), w2 AS (w3), w3 AS (w1)