mysql開窗函式
阿新 • • 發佈:2022-05-10
開窗函式
注:開窗函式只有MySQL8.0版本之後才有
1. 開窗函式
- 官網定義:A window function performs an aggregate-like operation on a set of query rows. However, whereas an aggregate operation groups query rows into a single result row, a window function produces a result for each query row。
- 開窗函式和像聚合函式一樣,查詢多行資料,然而,聚合操作將查詢行分組到單個結果行中,而視窗函式則為每個查詢行生成一個結果。
- 對其進行函式求值的行稱為當前行。
- 與進行函式計算的當前行相關的查詢行構成當前行的視窗。
MySQL提供的開窗函式
- DENSE_RNAK() :其分割槽中當前行的排名,無間隙
- FIRST_VALUE():視窗中第一行中的引數值
- LAG():分割槽中滯後當前行的行的引數值
- LAST_VALUE():視窗中最後一行中的引數值
- LEAD():分割槽中領先當前行的引數值
- NTILE():其分割槽中當前行的儲存桶編號。
- RANK():當前行在其分割槽內的排名,帶有間隙
- ROW_NUMBER():當前行在其分割槽內的排名,帶有間隙
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 | +----------+---------+------+-------+------+--------+--------+ 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 | +----------+------+------+------+----------+-----------+ 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 | +------+------------+--------+--------+
1.1 開窗函式和聚合函式的區別
- 資料
- 使用聚合函式的效果
SELECT
country,
SUM(profit) AS country_profit
FROM sales
GROUP BY country
ORDER BY country;
- 使用開窗函式的效果
SELECT year, country, product, profit, SUM(profit) OVER() AS total_profit, SUM(profit) OVER(PARTITION BY country) AS country_profit FROM sales ORDER BY country, year, product, profit;
第一個 OVER 子句為空,它將整個查詢行集視為單個分割槽。因此,視窗函式生成全域性和,但對每行都這樣做。
第二個 OVER 子句按country對行進行分割槽,從而生成country分割槽的總和。該函式為每個分割槽行生成此總和。
1.2 要使用開窗函式(或將聚合函式視為開窗函式),請在函式呼叫後包含一個 OVER 子句。OVER 子句有兩種形式:
-
over_clause:
{OVER (window_spec) | OVER window_name}這兩種形式都定義了視窗函式應如何處理查詢行。它們的不同之處在於,視窗是直接在 OVER 子句中定義,還是由對查詢中其他位置定義的命名視窗的引用提供:
- 在第一種情況下,視窗規範直接出現在 OVER 子句中,位於括號之間。
- 在第二種情況下,window_name是由查詢中其他位置的 WINDOW 子句定義的視窗規範的名稱。
-- 第一種情況
SELECT
year, country, product, profit,
ROW_NUMBER() OVER(PARTITION BY country) AS row_num1,
ROW_NUMBER() OVER(PARTITION BY country ORDER BY year, product) AS row_num2
FROM sales;
-- 第二種情況
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);
-
OVER (window_spec)語法
-
window_name:視窗函式名稱
- 視窗函式命名規則
- 視窗函式命名規則
-
partition_clause:子句指示如何將查詢行劃分為多個組。給定行的視窗函式結果基於包含該行的分割槽的行。如果省略了partition BY,則存在一個由所有查詢行組成的分割槽。
-
order_clause:如果省略 ORDER BY,則分割槽行是無序的,不隱含處理順序,並且所有分割槽行都是相同的。
-
1.3 開窗函式的執行順序
開窗函式只允許在select和 ORDER BY 子句中使用。查詢結果行 由 FROM 子句、在 WHERE、GROUP BY 和 HAVING 處理之後確定,並且視窗執行發生在 ORDER BY、LIMIT 和 SELECT DISTINCT 之前。
總結就是: 開窗函式在WHERE,GROUP BY 和 HAVING之後執行,在在 ORDER BY、LIMIT 和 SELECT DISTINCT 之前執行.
2. 聚合函式
聚合函式經常和開窗函式一起使用。