文档首页
MySQL 9.0 参考手册
相关文档 下载本手册
PDF (美国信纸) - 40.0Mb
PDF (A4) - 40.1Mb
手册页 (TGZ) - 258.2Kb
手册页 (Zip) - 365.3Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 9.0 参考手册  /  ...  /  命名窗口

14.20.4 命名窗口

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

WINDOW window_name AS (window_spec)
    [, window_name AS (window_spec)] ...

对于每个窗口定义,window_name 是窗口名称,而 window_specOVER 子句括号中提供的窗口规范相同,如 第 14.20.2 节,“窗口函数概念和语法” 中所述

window_spec:
    [window_name] [partition_clause] [order_clause] [frame_clause]

WINDOW 子句对于查询非常有用,在这些查询中,否则多个 OVER 子句将定义相同的窗口。相反,您可以只定义一次窗口,为其赋予名称,并在 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)