文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  ...  /  視窗函數描述

14.20.1 視窗函數描述

本節描述非聚合視窗函數,對於查詢中的每個資料列,使用與該資料列相關的資料列執行計算。大多數聚合函數也可以用作視窗函數;請參閱第 14.19.1 節,「聚合函數描述」

有關視窗函數的使用資訊和範例,以及諸如 OVER 子句、視窗、分割區、框架和同級等術語的定義,請參閱第 14.20.2 節,「視窗函數概念與語法」

表 14.30 視窗函數

名稱 描述
CUME_DIST() 累積分佈值
DENSE_RANK() 目前資料列在其分割區內的排名,不含間隙
FIRST_VALUE() 視窗框架第一列的引數值
LAG() 分割區內落後於目前資料列的資料列的引數值
LAST_VALUE() 視窗框架最後一列的引數值
LEAD() 分割區內領先於目前資料列的資料列的引數值
NTH_VALUE() 視窗框架第 N 列的引數值
NTILE() 目前資料列在其分割區內的儲存桶編號。
PERCENT_RANK() 百分比排名值
RANK() 目前資料列在其分割區內的排名,含間隙
ROW_NUMBER() 目前資料列在其分割區內的編號

在以下函數描述中,over_clause 代表 OVER 子句,如第 14.20.2 節,「視窗函數概念與語法」中所述。某些視窗函數允許使用 null_treatment 子句,指定計算結果時如何處理 NULL 值。此子句是選用的。它是 SQL 標準的一部分,但 MySQL 實作僅允許 RESPECT NULLS(這也是預設值)。這表示計算結果時會考慮 NULL 值。IGNORE NULLS 會被剖析,但會產生錯誤。

  • CUME_DIST() over_clause

    傳回值在值群組內的累積分佈;也就是說,分割區中小於或等於目前資料列中值的百分比。這表示在視窗分割區的視窗排序中,目前資料列之前或同級的資料列數除以視窗分割區中的總資料列數。傳回值範圍從 0 到 1。

    此函數應與 ORDER BY 一起使用,以將分割區資料列排序成所需的順序。若沒有 ORDER BY,則所有資料列都是同級,且值為 N/N = 1,其中 N 是分割區大小。

    over_clause第 14.20.2 節,「視窗函數概念與語法」中所述。

    以下查詢顯示,對於 val 資料行中的值集,每個資料列的 CUME_DIST() 值,以及類似的 PERCENT_RANK() 函數傳回的百分比排名值。為了參考,查詢也會使用 ROW_NUMBER() 顯示資料列編號

    mysql> SELECT
             val,
             ROW_NUMBER()   OVER w AS 'row_number',
             CUME_DIST()    OVER w AS 'cume_dist',
             PERCENT_RANK() OVER w AS 'percent_rank'
           FROM numbers
           WINDOW w AS (ORDER BY val);
    +------+------------+--------------------+--------------+
    | val  | row_number | cume_dist          | percent_rank |
    +------+------------+--------------------+--------------+
    |    1 |          1 | 0.2222222222222222 |            0 |
    |    1 |          2 | 0.2222222222222222 |            0 |
    |    2 |          3 | 0.3333333333333333 |         0.25 |
    |    3 |          4 | 0.6666666666666666 |        0.375 |
    |    3 |          5 | 0.6666666666666666 |        0.375 |
    |    3 |          6 | 0.6666666666666666 |        0.375 |
    |    4 |          7 | 0.8888888888888888 |         0.75 |
    |    4 |          8 | 0.8888888888888888 |         0.75 |
    |    5 |          9 |                  1 |            1 |
    +------+------------+--------------------+--------------+
  • DENSE_RANK() over_clause

    傳回目前資料列在其分割區內的排名,不含間隙。同級視為平手,並獲得相同的排名。此函數會為同級群組指定連續的排名;結果是,大小大於 1 的群組不會產生不連續的排名編號。如需範例,請參閱 RANK() 函數描述。

    此函數應與 ORDER BY 一起使用,以將分割區資料列排序成所需的順序。若沒有 ORDER BY,則所有資料列都是同級。

    over_clause第 14.20.2 節,「視窗函數概念與語法」中所述。

  • FIRST_VALUE(expr) [null_treatment] over_clause

    傳回視窗框架第一列的 expr 值。

    over_clause第 14.20.2 節,「視窗函數概念與語法」中所述。null_treatment 如本節介紹中所述。

    以下查詢示範 FIRST_VALUE()LAST_VALUE(),以及 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

  • LAG(expr [, N[, default]]) [null_treatment] over_clause

    傳回在分割區中,目前列之前第 N 列的 expr 值。如果沒有這樣的列,則傳回值為 default。例如,如果 N 為 3,則前三列的傳回值為 default。如果缺少 Ndefault,則預設值分別為 1 和 NULL

    N 必須是字面上的非負整數。如果 N 為 0,則會針對目前列評估 expr

    N 不能為 NULL,且必須是範圍從 0263(含)的整數,可以是下列任何形式

    • 無號整數常數字面值

    • 位置參數標記 (?)

    • 使用者定義的變數

    • 儲存常式中的區域變數

    over_clause第 14.20.2 節,「視窗函數概念與語法」中所述。null_treatment 如本節介紹中所述。

    LAG() (和類似的 LEAD() 函數) 通常用於計算列之間的差異。下列查詢顯示一組依時間排序的觀察值,以及每個觀察值相鄰列的 LAG()LEAD() 值,以及目前列與相鄰列之間的差異

    mysql> SELECT
             t, val,
             LAG(val)        OVER w AS 'lag',
             LEAD(val)       OVER w AS 'lead',
             val - LAG(val)  OVER w AS 'lag diff',
             val - LEAD(val) OVER w AS 'lead diff'
           FROM series
           WINDOW w AS (ORDER BY t);
    +----------+------+------+------+----------+-----------+
    | t        | val  | lag  | lead | lag diff | lead diff |
    +----------+------+------+------+----------+-----------+
    | 12:00:00 |  100 | NULL |  125 |     NULL |       -25 |
    | 13:00:00 |  125 |  100 |  132 |       25 |        -7 |
    | 14:00:00 |  132 |  125 |  145 |        7 |       -13 |
    | 15:00:00 |  145 |  132 |  140 |       13 |         5 |
    | 16:00:00 |  140 |  145 |  150 |       -5 |       -10 |
    | 17:00:00 |  150 |  140 |  200 |       10 |       -50 |
    | 18:00:00 |  200 |  150 | NULL |       50 |      NULL |
    +----------+------+------+------+----------+-----------+

    在此範例中,LAG()LEAD() 呼叫使用預設的 Ndefault 值,分別為 1 和 NULL

    第一列顯示當 LAG() 沒有前一列時會發生的情況:函數會傳回 default 值(在此情況下為 NULL)。最後一列顯示當 LEAD() 沒有下一列時會發生的情況。

    LAG()LEAD() 也可用於計算總和,而不是差異。請考慮此資料集,其中包含費波那契數列的前幾個數字

    mysql> SELECT n FROM fib ORDER BY n;
    +------+
    | n    |
    +------+
    |    1 |
    |    1 |
    |    2 |
    |    3 |
    |    5 |
    |    8 |
    +------+

    下列查詢顯示相鄰於目前列的列的 LAG()LEAD() 值。它也使用這些函數將目前列的值加上前一列和後一列的值。其效果是產生費波那契數列中的下一個數字,以及下下個數字

    mysql> SELECT
             n,
             LAG(n, 1, 0)      OVER w AS 'lag',
             LEAD(n, 1, 0)     OVER w AS 'lead',
             n + LAG(n, 1, 0)  OVER w AS 'next_n',
             n + LEAD(n, 1, 0) OVER w AS 'next_next_n'
           FROM fib
           WINDOW w AS (ORDER BY n);
    +------+------+------+--------+-------------+
    | n    | lag  | lead | next_n | next_next_n |
    +------+------+------+--------+-------------+
    |    1 |    0 |    1 |      1 |           2 |
    |    1 |    1 |    2 |      2 |           3 |
    |    2 |    1 |    3 |      3 |           5 |
    |    3 |    2 |    5 |      5 |           8 |
    |    5 |    3 |    8 |      8 |          13 |
    |    8 |    5 |    0 |     13 |           8 |
    +------+------+------+--------+-------------+

    產生初始費波那契數列的一種方法是使用遞迴通用資料表運算式。如需範例,請參閱費波那契數列產生

    您不能將負值用於此函數的列引數。

  • LAST_VALUE(expr) [null_treatment] over_clause

    傳回視窗框架中最後一列的 expr 值。

    over_clause第 14.20.2 節,「視窗函數概念與語法」中所述。null_treatment 如本節介紹中所述。

    如需範例,請參閱 FIRST_VALUE() 函數說明。

  • LEAD(expr [, N[, default]]) [null_treatment] over_clause

    傳回在分割區中,目前列之後第 N 列的 expr 值。如果沒有這樣的列,則傳回值為 default。例如,如果 N 為 3,則最後三列的傳回值為 default。如果缺少 Ndefault,則預設值分別為 1 和 NULL

    N 必須是字面上的非負整數。如果 N 為 0,則會針對目前列評估 expr

    N 不能為 NULL,且必須是範圍從 0263(含)的整數,可以是下列任何形式

    • 無號整數常數字面值

    • 位置參數標記 (?)

    • 使用者定義的變數

    • 儲存常式中的區域變數

    over_clause第 14.20.2 節,「視窗函數概念與語法」中所述。null_treatment 如本節介紹中所述。

    如需範例,請參閱 LAG() 函數說明。

    不允許將負值用於此函數的列引數。

  • NTH_VALUE(expr, N) [from_first_last] [null_treatment] over_clause

    傳回視窗框架中第 N 列的 expr 值。如果沒有這樣的列,則傳回值為 NULL

    N 必須是字面上的正整數。

    from_first_last 是 SQL 標準的一部分,但 MySQL 實作僅允許 FROM FIRST(這也是預設值)。這表示計算從視窗的第一列開始。FROM LAST 會被剖析,但會產生錯誤。若要取得與 FROM LAST 相同的效果(從視窗的最後一列開始計算),請使用 ORDER BY 以相反的順序排序。

    over_clause第 14.20.2 節,「視窗函數概念與語法」中所述。null_treatment 如本節介紹中所述。

    如需範例,請參閱 FIRST_VALUE() 函數說明。

    您不能將 NULL 用於此函數的列引數。

  • NTILE(N) over_clause

    將分割區分成 N 個群組(儲存桶),將分割區中的每一列指派其儲存桶編號,並傳回目前列在其分割區中的儲存桶編號。例如,如果 N 為 4,則 NTILE() 會將列分成四個儲存桶。如果 N 為 100,則 NTILE() 會將列分成 100 個儲存桶。

    N 必須是字面上的正整數。儲存桶編號傳回值的範圍從 1 到 N

    N 不能為 NULL,且必須是範圍從 0263(含)的整數,可以是下列任何形式

    • 無號整數常數字面值

    • 位置參數標記 (?)

    • 使用者定義的變數

    • 儲存常式中的區域變數

    此函數應與 ORDER BY 搭配使用,以將分割區列排序為所需的順序。

    over_clause第 14.20.2 節,「視窗函數概念與語法」中所述。

    下列查詢顯示 val 欄位中的一組值,將列分成兩組或四組所產生的百分位數值。為了方便參考,查詢也會使用 ROW_NUMBER() 顯示列編號

    mysql> SELECT
             val,
             ROW_NUMBER() OVER w AS 'row_number',
             NTILE(2)     OVER w AS 'ntile2',
             NTILE(4)     OVER w AS 'ntile4'
           FROM numbers
           WINDOW w AS (ORDER BY val);
    +------+------------+--------+--------+
    | val  | row_number | ntile2 | ntile4 |
    +------+------------+--------+--------+
    |    1 |          1 |      1 |      1 |
    |    1 |          2 |      1 |      1 |
    |    2 |          3 |      1 |      1 |
    |    3 |          4 |      1 |      2 |
    |    3 |          5 |      1 |      2 |
    |    3 |          6 |      2 |      3 |
    |    4 |          7 |      2 |      3 |
    |    4 |          8 |      2 |      4 |
    |    5 |          9 |      2 |      4 |
    +------+------------+--------+--------+

    不允許使用 NTILE(NULL) 建構。

  • PERCENT_RANK() over_clause

    傳回小於目前列中值的分割區值的百分比,不包括最大值。傳回值的範圍從 0 到 1,並代表列的相對排名,計算方式為此公式的結果,其中 rank 是列的排名,而 rows 是分割區列的數量

    (rank - 1) / (rows - 1)

    此函數應與 ORDER BY 一起使用,以將分割區資料列排序成所需的順序。若沒有 ORDER BY,則所有資料列都是同級。

    over_clause第 14.20.2 節,「視窗函數概念與語法」中所述。

    如需範例,請參閱 CUME_DIST() 函數說明。

  • RANK() over_clause

    傳回目前列在其分割區中的排名,並有間隙。對等項目視為平手,並獲得相同的排名。如果存在大小大於 1 的群組,則此函數不會將連續排名指派給對等群組;結果是非連續的排名數字。

    此函數應與 ORDER BY 一起使用,以將分割區資料列排序成所需的順序。若沒有 ORDER BY,則所有資料列都是同級。

    over_clause第 14.20.2 節,「視窗函數概念與語法」中所述。

    下列查詢顯示 RANK()(產生有間隙的排名)和 DENSE_RANK()(產生沒有間隙的排名)之間的差異。此查詢會顯示 val 欄位中一組值的每個成員的排名值,其中包含一些重複項。RANK() 會為對等項目(重複項)指派相同的排名值,而下一個較大的值的排名會比對等項目數減一高。DENSE_RANK() 也會為對等項目指派相同的排名值,但下一個較大的值的排名會大一。為了方便參考,查詢也會使用 ROW_NUMBER() 顯示列編號

    mysql> 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);
    +------+------------+------+------------+
    | val  | row_number | rank | dense_rank |
    +------+------------+------+------------+
    |    1 |          1 |    1 |          1 |
    |    1 |          2 |    1 |          1 |
    |    2 |          3 |    3 |          2 |
    |    3 |          4 |    4 |          3 |
    |    3 |          5 |    4 |          3 |
    |    3 |          6 |    4 |          3 |
    |    4 |          7 |    7 |          4 |
    |    4 |          8 |    7 |          4 |
    |    5 |          9 |    9 |          5 |
    +------+------------+------+------------+
  • ROW_NUMBER() over_clause

    傳回目前列在其分割區中的編號。列編號的範圍從 1 到分割區列的數量。

    ORDER BY 會影響列編號的順序。如果沒有 ORDER BY,列編號是不確定的。

    ROW_NUMBER() 會為對等項目指派不同的列編號。若要為對等項目指派相同的值,請使用 RANK()DENSE_RANK()。如需範例,請參閱 RANK() 函數說明。

    over_clause第 14.20.2 節,「視窗函數概念與語法」中所述。