type
status
date
slug
summary
tags
category
icon
password

前言

Window Function (下稱:窗口函數) 在統計類的需求中很常見,並且在其他數據庫(如:Oracle、MS SQL......等)在比較早的版本就實現了,MySQL 則是在 8.0 版本新增了這項功能,這項功能能夠簡化某些需求的 SQL 減少複雜度,接下來讓我們看看這項功能吧!
備註:MariaDB 是在 10.2.0 版本開始支援。

是什麼?

類似於 Aggregate Function (下稱:聚合函數),窗口函數會跨越當前行和其他行進行計算,但是卻不像聚合函數會將多個行合併成一個結果,而是維持原本的行數,如下圖:
notion image
notion image
如果看完上面的說明還是不太清楚,這邊舉個例子應該能很容易理解:
  • 排名:列出每個班級的學生按成績排名
    在上述例子中排名這個欄位是需要和其他行的資料進行計算,但是卻不需要合併,這就是窗口函數大展身手的時候。

    有哪些 function?

    除了以下窗口函數,還可以在窗口中使用聚合函數。
    Window Functions (1)
    Window Functions (1)
    Name
    描述
    支持 frame 子句
    聚合函數
    支持 frame 子句
    當前行在其分區中的排名 (會跳號,如:1,1,3)
    支持 frame 子句
    該行在其 partition 內的排名 (不跳號,如:1,1,2)
    支持 frame 子句
    分區內當前行號
    支持 frame 子句
    Percentage rank value,公式:(rank - 1) / (rows - 1)
    支持 frame 子句
    累積分配值,小(大)於等於當前行數 / 總行數
    支持 frame 子句
    返回分區內第 1 個值
    支持 frame 子句
    返回分區內最後 1 個值
    支持 frame 子句
    返回分區內第 N 個值
    支持 frame 子句
    將數據分成 N 個 Bucket,返回當前行所在的 Bucket
    支持 frame 子句
    獲取前 N 個行的值
    支持 frame 子句
    獲取後 N 個行的值
    支持 frame 子句

    怎麼寫?

    OVER

    在窗口函數或聚合函數後放加上 OVER 子句,才有辦法使用到窗口函數的功能,如下結構:
    第一種寫法就是直接將 OVER 子句寫在函數後方,如下範例:
    第二種寫法稱為命名窗口,會在 OVER 後方寫上窗口名稱,再最後才定義窗口內容 ,如下範例:
    關於命名窗口,詳細內容請查看:
    命名窗口
    命名窗口

    Window_spec

    OVER 裡面,我們可以看到需要填寫 window_spec,接下來讓我們看看 window_spec 的結構:

    partition 子句

    指示查詢如何將資料分組。
    結構:
    案例:
    • 沒有 PARTITION BY:將資料進行編號
      • 有 PARTITION BY:將資料按照class分組並進行編號,也就是說當class不同時必須重新從 1 開始編號。

        order 子句

        指示查詢如何對分組內的資料排序。
        結構:
        案例:
        此處表示將資料按照 class 分組,之後再透過 score 排序完成之後進行排名。

        frame 子句

        用來定義窗口的子集。詳細內容請查看:
        frame 子句
        frame 子句

        執行順序

        窗口函數的執行期間是在 FROMGROUP BY HAVING 之後,並在 ORDER BYLIMIT SELECT DISTINCT 之前。
        範例:

        參考