文档首页
MySQL 8.4 参考手册
8.4 中文镜像

MySQL 8.4 参考手册 · 中文镜像

正文为中文,英文原文默认隐藏。点击任意中文段落即可展开 / 收起对应英文原文。

打开官方英文原文 ↗

译文由机器翻译生成,仅供理解参考;有疑问请以官方英文原文为准。

中文点击中文段落可显示 / 隐藏英文原文本页译文覆盖 94%

14.20.3 窗口函数帧规范14.20.3 Window Function Frame Specification

用于窗口函数的窗口定义可以包含一个帧子句。帧是当前分区的一个子集,而帧子句指定如何定义该子集。The definition of a window used with a window function can include a frame clause. A frame is a subset of the current partition and the frame clause specifies how to define the subset.

帧是相对于当前行确定的,这使得帧可以根据当前行在其分区中的位置在分区内移动。示例:Frames are determined with respect to the current row, which enables a frame to move within a partition depending on the location of the current row within its partition. Examples:

  • 通过将帧定义为从分区开始到当前行的所有行,您可以计算每行的累计总和。By defining a frame to be all rows from the partition start to the current row, you can compute running totals for each row.

  • 通过将帧定义为在当前行的两侧各扩展N行,您可以计算滚动平均值。By defining a frame as extending N rows on either side of the current row, you can compute rolling averages.

下面的查询演示了使用移动帧在每组按时间排序的level值中计算运行总和,以及从当前行及其前后紧邻的行计算滚动平均值的方法:The following query demonstrates the use of moving frames to compute running totals within each group of time-ordered level values, as well as rolling averages computed from the current row and the rows that immediately precede and follow it:

mysql> SELECT
         time, subject, val,
         SUM(val) OVER (PARTITION BY subject ORDER BY time
                        ROWS UNBOUNDED PRECEDING)
           AS running_total,
         AVG(val) OVER (PARTITION BY subject ORDER BY time
                        ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)
           AS running_average
       FROM observations;
+----------+---------+------+---------------+-----------------+
| time     | subject | val  | running_total | running_average |
+----------+---------+------+---------------+-----------------+
| 07:00:00 | st113   |   10 |            10 |          9.5000 |
| 07:15:00 | st113   |    9 |            19 |         14.6667 |
| 07:30:00 | st113   |   25 |            44 |         18.0000 |
| 07:45:00 | st113   |   20 |            64 |         22.5000 |
| 07:00:00 | xh458   |    0 |             0 |          5.0000 |
| 07:15:00 | xh458   |   10 |            10 |          5.0000 |
| 07:30:00 | xh458   |    5 |            15 |         15.0000 |
| 07:45:00 | xh458   |   30 |            45 |         20.0000 |
| 08:00:00 | xh458   |   25 |            70 |         27.5000 |
+----------+---------+------+---------------+-----------------+

对于running_average列,第一行之前或最后一行之后没有帧行。在这些情况下,AVG()会计算可用行的平均值。For the running_average column, there is no frame row preceding the first one or following the last. In these cases, AVG() computes the average of the rows that are available.

作为窗口函数使用的聚合函数在当前行帧中的行上操作,非聚合窗口函数也是如此:Aggregate functions used as window functions operate on rows in the current row frame, as do these nonaggregate window functions:

FIRST_VALUE()
LAST_VALUE()
NTH_VALUE()

标准 SQL 指定,对整个分区操作的窗口函数不应有帧子句。MySQL 允许这些函数带帧子句,但会忽略它。即使指定了帧,这些函数也会使用整个分区:Standard SQL specifies that window functions that operate on the entire partition should have no frame clause. MySQL permits a frame clause for such functions but ignores it. These functions use the entire partition even if a frame is specified:

CUME_DIST()
DENSE_RANK()
LAG()
LEAD()
NTILE()
PERCENT_RANK()
RANK()
ROW_NUMBER()

如果给出了帧子句,其语法如下:The frame clause, if given, has this syntax:

frame_clause:
    frame_units frame_extent

frame_units:
    {ROWS | RANGE}

在没有帧子句的情况下,默认帧取决于是否存在 ORDER BY 子句,如本节后面所述。In the absence of a frame clause, the default frame depends on whether an ORDER BY clause is present, as described later in this section.

frame_units 值表示当前行与帧行之间的关系类型:The frame_units value indicates the type of relationship between the current row and frame rows:

  • ROWS:帧由起始和结束行位置定义。偏移量是当前行号与帧中行号之间的差值。ROWS: The frame is defined by beginning and ending row positions. Offsets are differences in row numbers from the current row number.

  • RANGE:帧由值范围内的行定义。偏移量是当前行值与帧中行值之间的差值。RANGE: The frame is defined by rows within a value range. Offsets are differences in row values from the current row value.

frame_extent 值表示帧的起点和终点。你可以只指定帧的起点(此时当前行为隐含的终点),或者使用 BETWEEN 来指定帧的两个端点:The frame_extent value indicates the start and end points of the frame. You can specify just the start of the frame (in which case the current row is implicitly the end) or use BETWEEN to specify both frame endpoints:

frame_extent:
    {frame_start | frame_between}

frame_between:
    BETWEEN frame_start AND frame_end

frame_start, frame_end: {
    CURRENT ROW
  | UNBOUNDED PRECEDING
  | UNBOUNDED FOLLOWING
  | expr PRECEDING
  | expr FOLLOWING
}

使用 BETWEEN 语法时,frame_start 不得晚于 frame_end。With BETWEEN syntax, frame_start must not occur later than frame_end.

允许的 frame_start 和 frame_end 值具有以下含义:The permitted frame_start and frame_end values have these meanings:

  • CURRENT ROW:对于 ROWS,界限为当前行。对于 RANGE,界限为当前行的同辈行。CURRENT ROW: For ROWS, the bound is the current row. For RANGE, the bound is the peers of the current row.

  • UNBOUNDED PRECEDING:界限为分区的第一行。UNBOUNDED PRECEDING: The bound is the first partition row.

  • UNBOUNDED FOLLOWING:界限为分区的最后一行。UNBOUNDED FOLLOWING: The bound is the last partition row.

  • expr PRECEDING:对于 ROWS,边界是当前行之前的 expr 行。对于 RANGE,边界是值等于当前行值减去 expr 的行;如果当前行值为 NULL,则边界是该行的同行。expr PRECEDING: For ROWS, the bound is expr rows before the current row. For RANGE, the bound is the rows with values equal to the current row value minus expr; if the current row value is NULL, the bound is the peers of the row.

    对于 expr PRECEDING(以及 expr FOLLOWING),expr 可以是 ? 参数标记(用于预处理语句)、非负数字字面值,或者形式为 INTERVAL val unit 的时间间隔。对于 INTERVAL 表达式,val 指定非负间隔值,unit 是一个关键字,表示该值应按何种单位来解释。(有关允许的 units 指定符的详细信息,请参阅 DATE_ADD() 函数在 第 14.7 节,“日期和时间函数” 中的描述。)For expr PRECEDING (and expr FOLLOWING), expr can be a ? parameter marker (for use in a prepared statement), a nonnegative numeric literal, or a temporal interval of the form INTERVAL val unit. For INTERVAL expressions, val specifies nonnegative interval value, and unit is a keyword indicating the units in which the value should be interpreted. (For details about the permitted units specifiers, see the description of the DATE_ADD() function in Section 14.7, “Date and Time Functions”.)

    RANGE 在数值或时间类型的 expr 上需要对相应的数值或时间表达式使用 ORDER BY。RANGE on a numeric or temporal expr requires ORDER BY on a numeric or temporal expression, respectively.

    有效的 expr PRECEDING 和 expr FOLLOWING 指示符示例:Examples of valid expr PRECEDING and expr FOLLOWING indicators:

    10 PRECEDING
    INTERVAL 5 DAY PRECEDING
    5 FOLLOWING
    INTERVAL '2:30' MINUTE_SECOND FOLLOWING
    
  • expr FOLLOWING:对于 ROWS,边界为当前行之后的 expr 行。对于 RANGE,边界为值等于当前行值加上 expr 的行;如果当前行值为 NULL,则边界为该行的同行。expr FOLLOWING: For ROWS, the bound is expr rows after the current row. For RANGE, the bound is the rows with values equal to the current row value plus expr; if the current row value is NULL, the bound is the peers of the row.

    有关允许的 expr 值,请参阅 expr PRECEDING 的说明。For permitted values of expr, see the description of expr PRECEDING.

下面的查询演示了 FIRST_VALUE()、LAST_VALUE() 以及两个 NTH_VALUE() 的用例:The following query demonstrates FIRST_VALUE(), LAST_VALUE(), and two instances of NTH_VALUE():

mysql> SELECT
         time, subject, val,
         FIRST_VALUE(val)  OVER w AS 'first',
         LAST_VALUE(val)   OVER w AS 'last',
         NTH_VALUE(val, 2) OVER w AS 'second',
         NTH_VALUE(val, 4) OVER w AS 'fourth'
       FROM observations
       WINDOW w AS (PARTITION BY subject ORDER BY time
                    ROWS UNBOUNDED PRECEDING);
+----------+---------+------+-------+------+--------+--------+
| time     | subject | val  | first | last | second | fourth |
+----------+---------+------+-------+------+--------+--------+
| 07:00:00 | st113   |   10 |    10 |   10 |   NULL |   NULL |
| 07:15:00 | st113   |    9 |    10 |    9 |      9 |   NULL |
| 07:30:00 | st113   |   25 |    10 |   25 |      9 |   NULL |
| 07:45:00 | st113   |   20 |    10 |   20 |      9 |     20 |
| 07:00:00 | xh458   |    0 |     0 |    0 |   NULL |   NULL |
| 07:15:00 | xh458   |   10 |     0 |   10 |     10 |   NULL |
| 07:30:00 | xh458   |    5 |     0 |    5 |     10 |   NULL |
| 07:45:00 | xh458   |   30 |     0 |   30 |     10 |     30 |
| 08:00:00 | xh458   |   25 |     0 |   25 |     10 |     30 |
+----------+---------+------+-------+------+--------+--------+

每个函数使用当前框架中的行,根据所示的窗口定义,该框架从第一个分区行延伸到当前行。对于 NTH_VALUE() 调用,当前框架并不总是包含请求的行;在这种情况下,返回值为 NULL。Each function uses the rows in the current frame, which, per the window definition shown, extends from the first partition row to the current row. For the NTH_VALUE() calls, the current frame does not always include the requested row; in such cases, the return value is NULL.

如果没有指定 frame 子句,默认的 frame 取决于是否存在 ORDER BY 子句:In the absence of a frame clause, the default frame depends on whether an ORDER BY clause is present:

  • 有 ORDER BY:默认的 frame 包括从分区开始到当前行的所有行,包括当前行的所有 peers(根据 ORDER BY 子句与当前行相等的行)。默认值等效于以下 frame 规格:With ORDER BY: The default frame includes rows from the partition start through the current row, including all peers of the current row (rows equal to the current row according to the ORDER BY clause). The default is equivalent to this frame specification:

    RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    
  • 没有 ORDER BY:默认的 frame 包括所有分区行(因为没有 ORDER BY 时,所有分区行都是 peers)。默认值等效于以下 frame 规格:Without ORDER BY: The default frame includes all partition rows (because, without ORDER BY, all partition rows are peers). The default is equivalent to this frame specification:

    RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
    

由于默认帧会根据是否存在 ORDER BY 而有所不同,因此在查询中添加 ORDER BY 以获得确定性结果可能会改变结果。(例如,由 SUM() 生成的值可能会发生变化。)为了获得相同的结果,但按 ORDER BY 排序,请提供一个明确的帧规范,无论是否存在 ORDER BY 都使用该规范。Because the default frame differs depending on presence or absence of ORDER BY, adding ORDER BY to a query to get deterministic results may change the results. (For example, the values produced by SUM() might change.) To obtain the same results but ordered per ORDER BY, provide an explicit frame specification to be used regardless of whether ORDER BY is present.

当当前行值为 NULL 时,帧规范的含义可能不明显。在这种假设下,这些示例说明了各种帧规范的应用方式:The meaning of a frame specification can be nonobvious when the current row value is NULL. Assuming that to be the case, these examples illustrate how various frame specifications apply:

  • ORDER BY X ASC RANGE BETWEEN 10 FOLLOWING AND 15 FOLLOWING

    帧从 NULL 开始,到 NULL 结束,因此只包含值为 NULL 的行。The frame starts at NULL and stops at NULL, thus includes only rows with value NULL.

  • ORDER BY X ASC RANGE BETWEEN 10 FOLLOWING AND UNBOUNDED FOLLOWING

    帧从 NULL 开始,到分区末尾结束。因为 ASC 排序将 NULL 值放在最前面,所以帧为整个分区。The frame starts at NULL and stops at the end of the partition. Because an ASC sort puts NULL values first, the frame is the entire partition.

  • ORDER BY X DESC RANGE BETWEEN 10 FOLLOWING AND UNBOUNDED FOLLOWING

    帧从 NULL 开始,到分区末尾结束。因为 DESC 排序将 NULL 值放在最后,所以帧只包含 NULL 值。The frame starts at NULL and stops at the end of the partition. Because a DESC sort puts NULL values last, the frame is only the NULL values.

  • ORDER BY X ASC RANGE BETWEEN 10 PRECEDING AND UNBOUNDED FOLLOWINGORDER BY X ASC RANGE BETWEEN 10 PRECEDING AND UNBOUNDED FOLLOWING

    帧从 NULL 开始,到分区末尾结束。因为 ASC 排序将 NULL 值放在最前面,所以帧为整个分区。The frame starts at NULL and stops at the end of the partition. Because an ASC sort puts NULL values first, the frame is the entire partition.

  • ORDER BY X ASC RANGE BETWEEN 10 PRECEDING AND 10 FOLLOWINGORDER BY X ASC RANGE BETWEEN 10 PRECEDING AND 10 FOLLOWING

    帧从 NULL 开始,到 NULL 结束,因此只包含值为 NULL 的行。The frame starts at NULL and stops at NULL, thus includes only rows with value NULL.

  • ORDER BY X ASC RANGE BETWEEN 10 PRECEDING AND 1 PRECEDINGORDER BY X ASC RANGE BETWEEN 10 PRECEDING AND 1 PRECEDING

    帧从 NULL 开始,到 NULL 结束,因此只包含值为 NULL 的行。The frame starts at NULL and stops at NULL, thus includes only rows with value NULL.

  • ORDER BY X ASC RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWINGORDER BY X ASC RANGE BETWEEN UNBOUNDED PRECEDING AND 10 FOLLOWING

    帧从分区的开始处开始,并在值为 NULL 的行处停止。因为 ASC 排序会将 NULL 值放在最前面,所以帧仅包含 NULL 值。The frame starts at the beginning of the partition and stops at rows with value NULL. Because an ASC sort puts NULL values first, the frame is only the NULL values.