文章目錄
- 概念:
- 語法:
- 常用的窗口函數及示例:
- 求平均值:AVG() :
- 求和:SUM():
- 求排名:
- 移動平均
- 計數COUNT():
- 求最大MXA()/小MIN()值
- 求分區內的最大/最小值
- 求當前行的前/后一個值
概念:
開窗函數是對于每條記錄 都要在此窗口內執行函數,它對數據的每一行 ,都使用與該行相關的行進行計算并返回計算結果。開窗函數的本質還是聚合運算,只不過它更具靈活性。
開窗函數和普通聚合函數的區別:
- 聚合函數是將多條記錄聚合為一條;而開窗函數是每條記錄都會執行,有幾條記錄執行完還是幾條。
- 聚合函數也可以用于開窗函數中。
應用:
窗口函數提供了在查詢結果中進行排序、排名、聚合和分析的靈活性。窗口函數在數據分析和報表生成中非常有用,可以實現更復雜的計算和分析需求。
語法:
window_function() OVER (
[PARTITION BY partition_expression]
[ORDER BY order_list]
[frame_clause] )
開窗函數的一個概念是當前行,當前行屬于某個窗口,窗口由over關鍵字用來指定函數執行的窗口范圍,如果后面括號中什么都不寫,則意味著窗口包含滿足where條件的所行,開窗函數基于所有行進行計算;如果不為空,則有三個參數來設置窗口:
- window_function(): 要使用的窗口函數,如:ROW_NUMBER(), RANK(), DENSE_RANK(), LEAD(), LAG(), SUM(), AVG() 等。
- PARTITION BY: 可選項,用于將結果集劃分為分區,以便窗口函數在每個分區內計算。
- ORDER BY: 可選項,用于指定結果集的排序順序,窗口函數將根據指定的排序順序進行計算。
- frame_clause: 可選項,用于指定窗口中要考慮的行的范圍。常見的 frame 類型包括 ROWS, RANGE 等,通常用來作為滑動窗口使用。
對于滑動窗口的范圍指定,通常使用 between frame_start and frame_end 語法來表示行范圍,frame_start和frame_end可以支持如下關鍵字,來確定不同的動態行記錄:
current row 邊界是當前行,一般和其他范圍關鍵字一起使用
unbounded preceding 邊界是分區中的第一行
unbounded following 邊界是分區中的最后一行
expr preceding 邊界是當前行減去expr的值
expr following 邊界是當前行加上expr的值
示例:
rows between 1 preceding and 1 following 窗口范圍是當前行、前一行、后一行一共三行記錄。
rows unbounded preceding 窗口范圍是當前行到分區中的最后一行。
rows between unbounded preceding and unbounded following 窗口范圍是當前分區中所有行,等同于不寫。
常用的窗口函數及示例:
以下是一些MySQL中常用的窗口函數:
示例數據: 銷售表包含以下列:銷售部門、銷售產品、銷售日期、銷售員、銷售數量、產品單價;(銷售額=銷售數量*產品單價)
CREATE TABLE sales (department VARCHAR(50),product VARCHAR(50),sale_date DATE,salesperson VARCHAR(50),quantity INT,unit_price DECIMAL(10,2)
);INSERT INTO sales (department, product, sale_date, salesperson, quantity, unit_price)
VALUES
('銷售1部','1001','2024/5/3','王明','15','200'),
('銷售2部','1002','2024/5/10','徐小小','20','500'),
('銷售3部','1002','2024/5/18','紀風','10','500'),
('銷售1部','1001','2024/5/5','王明','30','200'),
('銷售2部','1002','2024/5/12','徐小小','25','500'),
('銷售3部','1001','2024/5/20','紀風','18','200'),
('銷售1部','1001','2024/5/8','王明','12','200'),
('銷售2部','1002','2024/5/25','徐小小','22','500'),
('銷售2部','1003','2024/5/15','徐小小','8','1000'),
('銷售1部','1001','2024/5/30','王明','16','200'),
('銷售2部','1002','2024/5/1','徐小小','14','500'),
('銷售3部','1003','2024/5/22','紀風','19','1000'),
('銷售2部','1001','2024/5/7','徐小小','21','200'),
('銷售2部','1002','2024/5/28','劉陽','11','500'),
('銷售3部','1003','2024/5/17','紀風','24','1000'),
('銷售1部','1001','2024/5/4','王明','17','200'),
('銷售2部','1002','2024/5/13','劉陽','9','500'),
('銷售3部','1003','2024/5/21','紀風','23','1000'),
('銷售1部','1001','2024/5/29','張一','7','200'),
('銷售2部','1002','2024/5/6','劉陽','13','500'),
('銷售3部','1003','2024/5/23','付華','18','1000'),
('銷售1部','1001','2024/5/2','張一','20','200'),
('銷售2部','1002','2024/5/9','劉陽','10','500'),
('銷售3部','1003','2024/5/26','付華','30','1000'),
('銷售1部','1001','2024/5/14','張一','25','200'),
('銷售2部','1002','2024/5/31','劉陽','18','500'),
('銷售3部','1003','2024/5/24','付華','12','1000'),
('銷售1部','1001','2024/5/11','張一','22','200'),
('銷售2部','1002','2024/5/19','劉陽','8','500'),
('銷售3部','1003','2024/5/27','付華','16','1000'),
('銷售1部','1001','2024/5/16','張一','14','200'),
('銷售2部','1002','2024/5/3','劉陽','19','500'),
('銷售3部','1003','2024/5/20','付華','21','1000'),
('銷售1部','1001','2024/5/7','張一','11','200'),
('銷售2部','1002','2024/5/24','劉陽','24','500'),
('銷售3部','1003','2024/5/12','付華','17','1000'),
('銷售1部','1001','2024/5/29','張一','9','200'),
('銷售1部','1002','2024/5/5','張一','23','500'),
('銷售2部','1003','2024/5/22','劉陽','7','1000'),
('銷售3部','1001','2024/5/9','付華','13','200'),
('銷售1部','1002','2024/5/16','張一','18','500'),
('銷售2部','1003','2024/5/23','劉陽','20','1000'),
('銷售3部','1001','2024/5/1','付華','10','200'),
('銷售1部','1002','2024/5/18','張一','30','500'),
('銷售2部','1003','2024/5/25','劉陽','25','1000'),
('銷售3部','1001','2024/5/2','付華','18','200'),
('銷售1部','1002','2024/5/11','張一','10','500'),
('銷售2部','1003','2024/5/9','劉陽','50','1000'),
('銷售3部','1001','2024/5/10','付華','5','200');
求平均值:AVG() :
查詢各部門的平均銷售額(需保留全部行信息)
SELECT *,quantity*unit_price as sale,avg(quantity*unit_price) over(partition by department ) avg_sale from sales;
+-------+--------+-----------+------+------------+------+------+--------+-------
-----------+
| department | product | sale_date | salesperson | quantity | unit_price | sale | avg_sale |
| 銷售1部 | 1001 | 2024/5/3 | 王明 | 15 | 200 | 3000 | 5006.25 |
| 銷售1部 | 1001 | 2024/5/7 | 張一 | 11 | 200 | 2200 | 5006.25 |
| 銷售1部 | 1001 | 2024/5/29 | 張一 | 9 | 200 | 1800 | 5006.25 |
| 銷售1部 | 1001 | 2024/5/5 | 王明 | 30 | 200 | 6000 | 5006.25 |
| 銷售1部 | 1001 | 2024/5/29 | 張一 | 7 | 200 | 1400 | 5006.25 |
| 銷售1部 | 1002 | 2024/5/5 | 張一 | 23 | 500 | 11500 | 5006.25 |
| 銷售1部 | 1001 | 2024/5/8 | 王明 | 12 | 200 | 2400 | 5006.25 |
| 銷售1部 | 1002 | 2024/5/16 | 張一 | 18 | 500 | 9000 | 5006.25 |
| 銷售1部 | 1001 | 2024/5/2 | 張一 | 20 | 200 | 4000 | 5006.25 |
| 銷售1部 | 1001 | 2024/5/30 | 王明 | 16 | 200 | 3200 | 5006.25 |
| 銷售1部 | 1002 | 2024/5/18 | 張一 | 30 | 500 | 15000 | 5006.25 |
| 銷售1部 | 1002 | 2024/5/11 | 張一 | 10 | 500 | 5000 | 5006.25 |
| 銷售1部 | 1001 | 2024/5/14 | 張一 | 25 | 200 | 5000 | 5006.25 |
| 銷售1部 | 1001 | 2024/5/11 | 張一 | 22 | 200 | 4400 | 5006.25 |
| 銷售1部 | 1001 | 2024/5/16 | 張一 | 14 | 200 | 2800 | 5006.25 |
| 銷售1部 | 1001 | 2024/5/4 | 王明 | 17 | 200 | 3400 | 5006.25 |
| 銷售2部 | 1002 | 2024/5/10 | 徐小小 | 20 | 500 | 10000 | 11705.55556 |
| 銷售2部 | 1002 | 2024/5/6 | 劉陽 | 13 | 500 | 6500 | 11705.55556 |
| 銷售2部 | 1002 | 2024/5/12 | 徐小小 | 25 | 500 | 12500 | 11705.55556 |
| 銷售2部 | 1002 | 2024/5/13 | 劉陽 | 9 | 500 | 4500 | 11705.55556 |
| 銷售2部 | 1002 | 2024/5/25 | 徐小小 | 22 | 500 | 11000 | 11705.55556 |
| 銷售2部 | 1003 | 2024/5/15 | 徐小小 | 8 | 1000 | 8000 | 11705.55556 |
| 銷售2部 | 1002 | 2024/5/1 | 徐小小 | 14 | 500 | 7000 | 11705.55556 |
| 銷售2部 | 1002 | 2024/5/9 | 劉陽 | 10 | 500 | 5000 | 11705.55556 |
| 銷售2部 | 1001 | 2024/5/7 | 徐小小 | 21 | 200 | 4200 | 11705.55556 |
| 銷售2部 | 1002 | 2024/5/28 | 劉陽 | 11 | 500 | 5500 | 11705.55556 |
| 銷售2部 | 1002 | 2024/5/31 | 劉陽 | 18 | 500 | 9000 | 11705.55556 |
| 銷售2部 | 1002 | 2024/5/24 | 劉陽 | 24 | 500 | 12000 | 11705.55556 |
| 銷售2部 | 1002 | 2024/5/19 | 劉陽 | 8 | 500 | 4000 | 11705.55556 |
| 銷售2部 | 1003 | 2024/5/22 | 劉陽 | 7 | 1000 | 7000 | 11705.55556 |
| 銷售2部 | 1003 | 2024/5/23 | 劉陽 | 20 | 1000 | 20000 | 11705.55556 |
| 銷售2部 | 1002 | 2024/5/3 | 劉陽 | 19 | 500 | 9500 | 11705.55556 |
| 銷售2部 | 1003 | 2024/5/25 | 劉陽 | 25 | 1000 | 25000 | 11705.55556 |
| 銷售2部 | 1003 | 2024/5/9 | 劉陽 | 50 | 1000 | 50000 | 11705.55556 |
| 銷售3部 | 1001 | 2024/5/20 | 紀風 | 18 | 200 | 3600 | 13186.66667 |
| 銷售3部 | 1003 | 2024/5/12 | 付華 | 17 | 1000 | 17000 | 13186.66667 |
| 銷售3部 | 1003 | 2024/5/22 | 紀風 | 19 | 1000 | 19000 | 13186.66667 |
| 銷售3部 | 1003 | 2024/5/27 | 付華 | 16 | 1000 | 16000 | 13186.66667 |
| 銷售3部 | 1003 | 2024/5/17 | 紀風 | 24 | 1000 | 24000 | 13186.66667 |
| 銷售3部 | 1001 | 2024/5/9 | 付華 | 13 | 200 | 2600 | 13186.66667 |
| 銷售3部 | 1003 | 2024/5/24 | 付華 | 12 | 1000 | 12000 | 13186.66667 |
| 銷售3部 | 1003 | 2024/5/21 | 紀風 | 23 | 1000 | 23000 | 13186.66667 |
| 銷售3部 | 1001 | 2024/5/1 | 付華 | 10 | 200 | 2000 | 13186.66667 |
| 銷售3部 | 1003 | 2024/5/23 | 付華 | 18 | 1000 | 18000 | 13186.66667 |
| 銷售3部 | 1003 | 2024/5/26 | 付華 | 30 | 1000 | 30000 | 13186.66667 |
| 銷售3部 | 1001 | 2024/5/2 | 付華 | 18 | 200 | 3600 | 13186.66667 |
| 銷售3部 | 1003 | 2024/5/20 | 付華 | 21 | 1000 | 21000 | 13186.66667 |
| 銷售3部 | 1002 | 2024/5/18 | 紀風 | 10 | 500 | 5000 | 13186.66667 |
| 銷售3部 | 1001 | 2024/5/10 | 付華 | 5 | 200 | 1000 | 13186.66667 |
+-------+--------+-----------+------+------------+------+------+--------+
求和:SUM():
查詢每個產品的銷售總額:
SELECT product, SUM(quantity*unit_price) AS sale FROM sales GROUP BY product;
+-------+--------+-----------+------+------------+------+------+--------+
| product | sale |
| 1001 | 56600 |
| 1002 | 142000 |
| 1003 | 290000 |
+-------+--------+-----------+------+------------+------+------+--------+
求排名:
- row_number(): 顯示分區中不重復不間斷的序號
- dense_rank(): 顯示分區中重復不間斷的序號
- rank() 顯示分區中重復間斷的序號
計算每個產品在每個日期的銷售量排名:
SELECT product,quantity,unit_price,sale_date,RANK() OVER (PARTITION BY sale_date, product ORDER BY quantity DESC) AS sale_rank FROM sales ORDER BY sale_date, product, quantity DESC;
+-------+--------+-----------+------+------------+------+------+--------+-------
-----------+
| product | quantity | unit_price | sale_date | sales_rank |
| 1001 | 10 | 200 | 2024/5/1 | 1 |
| 1002 | 14 | 500 | 2024/5/1 | 1 |
| 1001 | 20 | 200 | 2024/5/2 | 1 |
| 1001 | 18 | 200 | 2024/5/2 | 2 |
| 1001 | 15 | 200 | 2024/5/3 | 1 |
| 1002 | 19 | 500 | 2024/5/3 | 1 |
| 1001 | 17 | 200 | 2024/5/4 | 1 |
| 1001 | 30 | 200 | 2024/5/5 | 1 |
| 1002 | 23 | 500 | 2024/5/5 | 1 |
| 1002 | 13 | 500 | 2024/5/6 | 1 |
| 1001 | 21 | 200 | 2024/5/7 | 1 |
| 1001 | 11 | 200 | 2024/5/7 | 2 |
| 1001 | 12 | 200 | 2024/5/8 | 1 |
| 1001 | 13 | 200 | 2024/5/9 | 1 |
| 1002 | 10 | 500 | 2024/5/9 | 1 |
| 1003 | 50 | 1000 | 2024/5/9 | 1 |
| 1001 | 5 | 200 | 2024/5/10 | 1 |
| 1002 | 20 | 500 | 2024/5/10 | 1 |
| 1001 | 22 | 200 | 2024/5/11 | 1 |
| 1002 | 10 | 500 | 2024/5/11 | 1 |
| 1002 | 25 | 500 | 2024/5/12 | 1 |
| 1003 | 17 | 1000 | 2024/5/12 | 1 |
| 1002 | 9 | 500 | 2024/5/13 | 1 |
| 1001 | 25 | 200 | 2024/5/14 | 1 |
| 1003 | 8 | 1000 | 2024/5/15 | 1 |
| 1001 | 14 | 200 | 2024/5/16 | 1 |
| 1002 | 18 | 500 | 2024/5/16 | 1 |
| 1003 | 24 | 1000 | 2024/5/17 | 1 |
| 1002 | 30 | 500 | 2024/5/18 | 1 |
| 1002 | 10 | 500 | 2024/5/18 | 2 |
| 1002 | 8 | 500 | 2024/5/19 | 1 |
| 1001 | 18 | 200 | 2024/5/20 | 1 |
| 1003 | 21 | 1000 | 2024/5/20 | 1 |
| 1003 | 23 | 1000 | 2024/5/21 | 1 |
| 1003 | 19 | 1000 | 2024/5/22 | 1 |
| 1003 | 7 | 1000 | 2024/5/22 | 2 |
| 1003 | 20 | 1000 | 2024/5/23 | 1 |
| 1003 | 18 | 1000 | 2024/5/23 | 2 |
| 1002 | 24 | 500 | 2024/5/24 | 1 |
| 1003 | 12 | 1000 | 2024/5/24 | 1 |
| 1002 | 22 | 500 | 2024/5/25 | 1 |
| 1003 | 25 | 1000 | 2024/5/25 | 1 |
| 1003 | 30 | 1000 | 2024/5/26 | 1 |
| 1003 | 16 | 1000 | 2024/5/27 | 1 |
| 1002 | 11 | 500 | 2024/5/28 | 1 |
| 1001 | 9 | 200 | 2024/5/29 | 1 |
| 1001 | 7 | 200 | 2024/5/29 | 2 |
| 1001 | 16 | 200 | 2024/5/30 | 1 |
| 1002 | 18 | 500 | 2024/5/31 | 1 |
+-------+--------+-----------+------+------------+------+------+--------+-------
-----------+
移動平均
計算每個產品的移動平均銷售額(最近3個訂單):
SELECTproduct,quantity*unit_price sale,sale_date,AVG(quantity*unit_price) OVER (PARTITION BY product ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg_sale
FROM sales
ORDER BY product, sale_date;
+-------+--------+-----------+------+------------+------+------+--------+-------
-----------+
| product | sale | sale_date | moving_avg_sale |
| 1001 | 2000 | 2024/5/1 | 2000 |
| 1001 | 3600 | 2024/5/2 | 2800 |
| 1001 | 4000 | 2024/5/2 | 3200 |
| 1001 | 3000 | 2024/5/3 | 3533.333333 |
| 1001 | 3400 | 2024/5/4 | 3466.666667 |
| 1001 | 6000 | 2024/5/5 | 4133.333333 |
| 1001 | 2200 | 2024/5/7 | 3866.666667 |
| 1001 | 4200 | 2024/5/7 | 4133.333333 |
| 1001 | 2400 | 2024/5/8 | 2933.333333 |
| 1001 | 2600 | 2024/5/9 | 3066.666667 |
| 1001 | 1000 | 2024/5/10 | 2000 |
| 1001 | 4400 | 2024/5/11 | 2666.666667 |
| 1001 | 5000 | 2024/5/14 | 3466.666667 |
| 1001 | 2800 | 2024/5/16 | 4066.666667 |
| 1001 | 3600 | 2024/5/20 | 3800 |
| 1001 | 1400 | 2024/5/29 | 2600 |
| 1001 | 1800 | 2024/5/29 | 2266.666667 |
| 1001 | 3200 | 2024/5/30 | 2133.333333 |
| 1002 | 7000 | 2024/5/1 | 7000 |
| 1002 | 9500 | 2024/5/3 | 8250 |
| 1002 | 11500 | 2024/5/5 | 9333.333333 |
| 1002 | 6500 | 2024/5/6 | 9166.666667 |
| 1002 | 5000 | 2024/5/9 | 7666.666667 |
| 1002 | 10000 | 2024/5/10 | 7166.666667 |
| 1002 | 5000 | 2024/5/11 | 6666.666667 |
| 1002 | 12500 | 2024/5/12 | 9166.666667 |
| 1002 | 4500 | 2024/5/13 | 7333.333333 |
| 1002 | 9000 | 2024/5/16 | 8666.666667 |
| 1002 | 5000 | 2024/5/18 | 6166.666667 |
| 1002 | 15000 | 2024/5/18 | 9666.666667 |
| 1002 | 4000 | 2024/5/19 | 8000 |
| 1002 | 12000 | 2024/5/24 | 10333.33333 |
| 1002 | 11000 | 2024/5/25 | 9000 |
| 1002 | 5500 | 2024/5/28 | 9500 |
| 1002 | 9000 | 2024/5/31 | 8500 |
| 1003 | 50000 | 2024/5/9 | 50000 |
| 1003 | 17000 | 2024/5/12 | 33500 |
| 1003 | 8000 | 2024/5/15 | 25000 |
| 1003 | 24000 | 2024/5/17 | 16333.33333 |
| 1003 | 21000 | 2024/5/20 | 17666.66667 |
| 1003 | 23000 | 2024/5/21 | 22666.66667 |
| 1003 | 19000 | 2024/5/22 | 21000 |
| 1003 | 7000 | 2024/5/22 | 16333.33333 |
| 1003 | 18000 | 2024/5/23 | 14666.66667 |
| 1003 | 20000 | 2024/5/23 | 15000 |
| 1003 | 12000 | 2024/5/24 | 16666.66667 |
| 1003 | 25000 | 2024/5/25 | 19000 |
| 1003 | 30000 | 2024/5/26 | 22333.33333 |
| 1003 | 16000 | 2024/5/27 | 23666.66667 |
+-------+--------+-----------+------+------------+------+------+--------+-------
-----------+
計數COUNT():
示例: 計算每個部門的銷售記錄總和:
SELECTdepartment,COUNT(1) OVER (PARTITION BY department) AS total_sales_count
FROM sales;
+-------+--------+-----------+------+------------+------+------+--------+-------
-----------+
| department | total_sales_count |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售1部 | 16 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售2部 | 18 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
| 銷售3部 | 15 |
+-------+--------+-----------+------+------------+------+------+--------+-------
-----------+
求最大MXA()/小MIN()值
示例: 查找每個部門在銷售日期的最大銷售數量:
SELECTdepartment,sale_date,quantity,MAX(quantity) OVER (PARTITION BY department, sale_date) AS max_quantity_on_date
FROM sales;
+-------+--------+-----------+------+------------+------+------+--------+-------
-----------+
| department | sale_date | quantity | max_quantity_on_date |
| 銷售1部 | 2024/5/2 | 20 | 20 |
| 銷售1部 | 2024/5/3 | 15 | 15 |
| 銷售1部 | 2024/5/4 | 17 | 17 |
| 銷售1部 | 2024/5/5 | 30 | 30 |
| 銷售1部 | 2024/5/5 | 23 | 30 |
| 銷售1部 | 2024/5/7 | 11 | 11 |
| 銷售1部 | 2024/5/8 | 12 | 12 |
| 銷售1部 | 2024/5/11 | 22 | 22 |
| 銷售1部 | 2024/5/11 | 10 | 22 |
| 銷售1部 | 2024/5/14 | 25 | 25 |
| 銷售1部 | 2024/5/16 | 14 | 18 |
| 銷售1部 | 2024/5/16 | 18 | 18 |
| 銷售1部 | 2024/5/18 | 30 | 30 |
| 銷售1部 | 2024/5/29 | 7 | 9 |
| 銷售1部 | 2024/5/29 | 9 | 9 |
| 銷售1部 | 2024/5/30 | 16 | 16 |
| 銷售2部 | 2024/5/1 | 14 | 14 |
| 銷售2部 | 2024/5/3 | 19 | 19 |
| 銷售2部 | 2024/5/6 | 13 | 13 |
| 銷售2部 | 2024/5/7 | 21 | 21 |
| 銷售2部 | 2024/5/9 | 10 | 50 |
| 銷售2部 | 2024/5/9 | 50 | 50 |
| 銷售2部 | 2024/5/10 | 20 | 20 |
| 銷售2部 | 2024/5/12 | 25 | 25 |
| 銷售2部 | 2024/5/13 | 9 | 9 |
| 銷售2部 | 2024/5/15 | 8 | 8 |
| 銷售2部 | 2024/5/19 | 8 | 8 |
| 銷售2部 | 2024/5/22 | 7 | 7 |
| 銷售2部 | 2024/5/23 | 20 | 20 |
| 銷售2部 | 2024/5/24 | 24 | 24 |
| 銷售2部 | 2024/5/25 | 22 | 25 |
| 銷售2部 | 2024/5/25 | 25 | 25 |
| 銷售2部 | 2024/5/28 | 11 | 11 |
| 銷售2部 | 2024/5/31 | 18 | 18 |
| 銷售3部 | 2024/5/1 | 10 | 10 |
| 銷售3部 | 2024/5/2 | 18 | 18 |
| 銷售3部 | 2024/5/9 | 13 | 13 |
| 銷售3部 | 2024/5/10 | 5 | 5 |
| 銷售3部 | 2024/5/12 | 17 | 17 |
| 銷售3部 | 2024/5/17 | 24 | 24 |
| 銷售3部 | 2024/5/18 | 10 | 10 |
| 銷售3部 | 2024/5/20 | 18 | 21 |
| 銷售3部 | 2024/5/20 | 21 | 21 |
| 銷售3部 | 2024/5/21 | 23 | 23 |
| 銷售3部 | 2024/5/22 | 19 | 19 |
| 銷售3部 | 2024/5/23 | 18 | 18 |
| 銷售3部 | 2024/5/24 | 12 | 12 |
| 銷售3部 | 2024/5/26 | 30 | 30 |
| 銷售3部 | 2024/5/27 | 16 | 16 |
+-------+--------+-----------+------+------------+------+------+--------+-------
-----------+
示例: 查找每個部門在銷售日期的最小銷售數量:
SELECTdepartment,sale_date,quantity,MAX(quantity) OVER (PARTITION BY department, sale_date) AS max_quantity_on_date
FROM sales;
+-------+--------+-----------+------+------------+------+------+--------+-------
-----------+
| department | sale_date | quantity | min_quantity_on_date |
| 銷售1部 | 2024/5/2 | 20 | 20 |
| 銷售1部 | 2024/5/3 | 15 | 15 |
| 銷售1部 | 2024/5/4 | 17 | 17 |
| 銷售1部 | 2024/5/5 | 30 | 23 |
| 銷售1部 | 2024/5/5 | 23 | 23 |
| 銷售1部 | 2024/5/7 | 11 | 11 |
| 銷售1部 | 2024/5/8 | 12 | 12 |
| 銷售1部 | 2024/5/11 | 22 | 10 |
| 銷售1部 | 2024/5/11 | 10 | 10 |
| 銷售1部 | 2024/5/14 | 25 | 25 |
| 銷售1部 | 2024/5/16 | 14 | 14 |
| 銷售1部 | 2024/5/16 | 18 | 14 |
| 銷售1部 | 2024/5/18 | 30 | 30 |
| 銷售1部 | 2024/5/29 | 7 | 7 |
| 銷售1部 | 2024/5/29 | 9 | 7 |
| 銷售1部 | 2024/5/30 | 16 | 16 |
| 銷售2部 | 2024/5/1 | 14 | 14 |
| 銷售2部 | 2024/5/3 | 19 | 19 |
| 銷售2部 | 2024/5/6 | 13 | 13 |
| 銷售2部 | 2024/5/7 | 21 | 21 |
| 銷售2部 | 2024/5/9 | 10 | 10 |
| 銷售2部 | 2024/5/9 | 50 | 10 |
| 銷售2部 | 2024/5/10 | 20 | 20 |
| 銷售2部 | 2024/5/12 | 25 | 25 |
| 銷售2部 | 2024/5/13 | 9 | 9 |
| 銷售2部 | 2024/5/15 | 8 | 8 |
| 銷售2部 | 2024/5/19 | 8 | 8 |
| 銷售2部 | 2024/5/22 | 7 | 7 |
| 銷售2部 | 2024/5/23 | 20 | 20 |
| 銷售2部 | 2024/5/24 | 24 | 24 |
| 銷售2部 | 2024/5/25 | 22 | 22 |
| 銷售2部 | 2024/5/25 | 25 | 22 |
| 銷售2部 | 2024/5/28 | 11 | 11 |
| 銷售2部 | 2024/5/31 | 18 | 18 |
| 銷售3部 | 2024/5/1 | 10 | 10 |
| 銷售3部 | 2024/5/2 | 18 | 18 |
| 銷售3部 | 2024/5/9 | 13 | 13 |
| 銷售3部 | 2024/5/10 | 5 | 5 |
| 銷售3部 | 2024/5/12 | 17 | 17 |
| 銷售3部 | 2024/5/17 | 24 | 24 |
| 銷售3部 | 2024/5/18 | 10 | 10 |
| 銷售3部 | 2024/5/20 | 18 | 18 |
| 銷售3部 | 2024/5/20 | 21 | 18 |
| 銷售3部 | 2024/5/21 | 23 | 23 |
| 銷售3部 | 2024/5/22 | 19 | 19 |
| 銷售3部 | 2024/5/23 | 18 | 18 |
| 銷售3部 | 2024/5/24 | 12 | 12 |
| 銷售3部 | 2024/5/26 | 30 | 30 |
| 銷售3部 | 2024/5/27 | 16 | 16 |
+-------+--------+-----------+------+------------+------+------+--------+-------
-----------+
求分區內的最大/最小值
- FIRST_VALUE() OVER(PARTITION BY … ORDER BY …):
作用: 返回在指定分區內按指定排序順序的第一個值。
應用: 常用于找出每個分組內的第一個值。
示例: 找出每個部門的最早銷售日期:
SELECTdepartment,sale_date,FIRST_VALUE(sale_date) OVER (PARTITION BY department ORDER BY sale_date) AS first_sale_date
FROM sales;
+-------+--------+-----------+------+------------+------+------+--------+
| department | sale_date | first_sale_date |
| 銷售1部 | 2024/5/2 | 2024/5/2 |
| 銷售1部 | 2024/5/3 | 2024/5/2 |
| 銷售1部 | 2024/5/4 | 2024/5/2 |
| 銷售1部 | 2024/5/5 | 2024/5/2 |
| 銷售1部 | 2024/5/5 | 2024/5/2 |
| 銷售1部 | 2024/5/7 | 2024/5/2 |
| 銷售1部 | 2024/5/8 | 2024/5/2 |
| 銷售1部 | 2024/5/11 | 2024/5/2 |
| 銷售1部 | 2024/5/11 | 2024/5/2 |
| 銷售1部 | 2024/5/14 | 2024/5/2 |
| 銷售1部 | 2024/5/16 | 2024/5/2 |
| 銷售1部 | 2024/5/16 | 2024/5/2 |
| 銷售1部 | 2024/5/18 | 2024/5/2 |
| 銷售1部 | 2024/5/29 | 2024/5/2 |
| 銷售1部 | 2024/5/29 | 2024/5/2 |
| 銷售1部 | 2024/5/30 | 2024/5/2 |
| 銷售2部 | 2024/5/1 | 2024/5/1 |
| 銷售2部 | 2024/5/3 | 2024/5/1 |
| 銷售2部 | 2024/5/6 | 2024/5/1 |
| 銷售2部 | 2024/5/7 | 2024/5/1 |
| 銷售2部 | 2024/5/9 | 2024/5/1 |
| 銷售2部 | 2024/5/9 | 2024/5/1 |
| 銷售2部 | 2024/5/10 | 2024/5/1 |
| 銷售2部 | 2024/5/12 | 2024/5/1 |
| 銷售2部 | 2024/5/13 | 2024/5/1 |
| 銷售2部 | 2024/5/15 | 2024/5/1 |
| 銷售2部 | 2024/5/19 | 2024/5/1 |
| 銷售2部 | 2024/5/22 | 2024/5/1 |
| 銷售2部 | 2024/5/23 | 2024/5/1 |
| 銷售2部 | 2024/5/24 | 2024/5/1 |
| 銷售2部 | 2024/5/25 | 2024/5/1 |
| 銷售2部 | 2024/5/25 | 2024/5/1 |
| 銷售2部 | 2024/5/28 | 2024/5/1 |
| 銷售2部 | 2024/5/31 | 2024/5/1 |
| 銷售3部 | 2024/5/1 | 2024/5/1 |
| 銷售3部 | 2024/5/2 | 2024/5/1 |
| 銷售3部 | 2024/5/9 | 2024/5/1 |
| 銷售3部 | 2024/5/10 | 2024/5/1 |
| 銷售3部 | 2024/5/12 | 2024/5/1 |
| 銷售3部 | 2024/5/17 | 2024/5/1 |
| 銷售3部 | 2024/5/18 | 2024/5/1 |
| 銷售3部 | 2024/5/20 | 2024/5/1 |
| 銷售3部 | 2024/5/20 | 2024/5/1 |
| 銷售3部 | 2024/5/21 | 2024/5/1 |
| 銷售3部 | 2024/5/22 | 2024/5/1 |
| 銷售3部 | 2024/5/23 | 2024/5/1 |
| 銷售3部 | 2024/5/24 | 2024/5/1 |
| 銷售3部 | 2024/5/26 | 2024/5/1 |
| 銷售3部 | 2024/5/27 | 2024/5/1 |
+-------+--------+-----------+------+------------+------+------+--------+
- LAST_VALUE() OVER(PARTITION BY … ORDER BY …):
作用: 返回在指定分區內按指定排序順序的最后一個值。
應用: 由于 MySQL 中并沒有內置的 LAST_VALUE 函數,可以通過 ROW_NUMBER 窗口函數先給每行分配一個序號,然后利用 MAX() 函數結合 CASE 表達式來實現類似功能。
示例: 找出每個部門的最晚銷售日期:
SELECTdepartment,sale_date,LAST_VALUE(sale_date) OVER (PARTITION BY department ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_sale_date
FROM sales;
+-------+--------+-----------+------+------------+------+------+--------+
| department | sale_date | last_sale_date |
| 銷售1部 | 2024/5/2 | 2024/5/30 |
| 銷售1部 | 2024/5/3 | 2024/5/30 |
| 銷售1部 | 2024/5/4 | 2024/5/30 |
| 銷售1部 | 2024/5/5 | 2024/5/30 |
| 銷售1部 | 2024/5/5 | 2024/5/30 |
| 銷售1部 | 2024/5/7 | 2024/5/30 |
| 銷售1部 | 2024/5/8 | 2024/5/30 |
| 銷售1部 | 2024/5/11 | 2024/5/30 |
| 銷售1部 | 2024/5/11 | 2024/5/30 |
| 銷售1部 | 2024/5/14 | 2024/5/30 |
| 銷售1部 | 2024/5/16 | 2024/5/30 |
| 銷售1部 | 2024/5/16 | 2024/5/30 |
| 銷售1部 | 2024/5/18 | 2024/5/30 |
| 銷售1部 | 2024/5/29 | 2024/5/30 |
| 銷售1部 | 2024/5/29 | 2024/5/30 |
| 銷售1部 | 2024/5/30 | 2024/5/30 |
| 銷售2部 | 2024/5/1 | 2024/5/31 |
| 銷售2部 | 2024/5/3 | 2024/5/31 |
| 銷售2部 | 2024/5/6 | 2024/5/31 |
| 銷售2部 | 2024/5/7 | 2024/5/31 |
| 銷售2部 | 2024/5/9 | 2024/5/31 |
| 銷售2部 | 2024/5/9 | 2024/5/31 |
| 銷售2部 | 2024/5/10 | 2024/5/31 |
| 銷售2部 | 2024/5/12 | 2024/5/31 |
| 銷售2部 | 2024/5/13 | 2024/5/31 |
| 銷售2部 | 2024/5/15 | 2024/5/31 |
| 銷售2部 | 2024/5/19 | 2024/5/31 |
| 銷售2部 | 2024/5/22 | 2024/5/31 |
| 銷售2部 | 2024/5/23 | 2024/5/31 |
| 銷售2部 | 2024/5/24 | 2024/5/31 |
| 銷售2部 | 2024/5/25 | 2024/5/31 |
| 銷售2部 | 2024/5/25 | 2024/5/31 |
| 銷售2部 | 2024/5/28 | 2024/5/31 |
| 銷售2部 | 2024/5/31 | 2024/5/31 |
| 銷售3部 | 2024/5/1 | 2024/5/27 |
| 銷售3部 | 2024/5/2 | 2024/5/27 |
| 銷售3部 | 2024/5/9 | 2024/5/27 |
| 銷售3部 | 2024/5/10 | 2024/5/27 |
| 銷售3部 | 2024/5/12 | 2024/5/27 |
| 銷售3部 | 2024/5/17 | 2024/5/27 |
| 銷售3部 | 2024/5/18 | 2024/5/27 |
| 銷售3部 | 2024/5/20 | 2024/5/27 |
| 銷售3部 | 2024/5/20 | 2024/5/27 |
| 銷售3部 | 2024/5/21 | 2024/5/27 |
| 銷售3部 | 2024/5/22 | 2024/5/27 |
| 銷售3部 | 2024/5/23 | 2024/5/27 |
| 銷售3部 | 2024/5/24 | 2024/5/27 |
| 銷售3部 | 2024/5/26 | 2024/5/27 |
| 銷售3部 | 2024/5/27 | 2024/5/27 |
+-------+--------+-----------+------+------------+------+------+--------+
求當前行的前/后一個值
- LAG() OVER(PARTITION BY … ORDER BY …):
作用: 用于獲取指定列在指定排序順序下的前一個值。
應用: 常用于比較相鄰行的值。
示例: 找出銷售量比上一次銷售量增加的產品:
select * from (
select department,product,sale_date,quantity,LAG(quantity) OVER (PARTITION BY department, product ORDER BY sale_date) AS previous_quantity
FROM sales ) t1
where quantity > previous_quantity;
+-------+--------+-----------+------+------------+------+------+--------+
| department | product | sale_date | quantity | previous_quantity |
| 銷售1部 | 1001 | 2024/5/4 | 17 | 15 |
| 銷售1部 | 1001 | 2024/5/5 | 30 | 17 |
| 銷售1部 | 1001 | 2024/5/8 | 12 | 11 |
| 銷售1部 | 1001 | 2024/5/11 | 22 | 12 |
| 銷售1部 | 1001 | 2024/5/14 | 25 | 22 |
| 銷售1部 | 1001 | 2024/5/30 | 16 | 7 |
| 銷售1部 | 1002 | 2024/5/16 | 18 | 10 |
| 銷售1部 | 1002 | 2024/5/18 | 30 | 18 |
| 銷售2部 | 1002 | 2024/5/3 | 19 | 14 |
| 銷售2部 | 1002 | 2024/5/10 | 20 | 10 |
| 銷售2部 | 1002 | 2024/5/12 | 25 | 20 |
| 銷售2部 | 1002 | 2024/5/24 | 24 | 8 |
| 銷售2部 | 1002 | 2024/5/31 | 18 | 11 |
| 銷售2部 | 1003 | 2024/5/23 | 20 | 7 |
| 銷售2部 | 1003 | 2024/5/25 | 25 | 20 |
| 銷售3部 | 1001 | 2024/5/2 | 18 | 10 |
| 銷售3部 | 1001 | 2024/5/20 | 18 | 5 |
| 銷售3部 | 1003 | 2024/5/17 | 24 | 17 |
| 銷售3部 | 1003 | 2024/5/21 | 23 | 21 |
| 銷售3部 | 1003 | 2024/5/26 | 30 | 12 |
+-------+--------+-----------+------+------------+------+------+--------+
- LEAD() OVER(PARTITION BY … ORDER BY …):
作用: 用于獲取指定列在指定排序順序下的后一個值。
應用: 常用于比較相鄰行的值。
示例: 找出下一次銷售量較本次銷量減少的產品:
select * from (
selectdepartment,product,sale_date,quantity,LEAD(quantity) OVER (PARTITION BY department, product ORDER BY sale_date) AS next_quantity
FROM sales
) t1
where quantity > next_quantity;
+-------+--------+-----------+------+------------+------+------+--------+
| department | product | sale_date | quantity | next_quantity |
| 銷售1部 | 1001 | 2024/5/2 | 20 | 15 |
| 銷售1部 | 1001 | 2024/5/5 | 30 | 11 |
| 銷售1部 | 1001 | 2024/5/14 | 25 | 14 |
| 銷售1部 | 1001 | 2024/5/16 | 14 | 9 |
| 銷售1部 | 1001 | 2024/5/29 | 9 | 7 |
| 銷售1部 | 1002 | 2024/5/5 | 23 | 10 |
| 銷售2部 | 1002 | 2024/5/3 | 19 | 13 |
| 銷售2部 | 1002 | 2024/5/6 | 13 | 10 |
| 銷售2部 | 1002 | 2024/5/12 | 25 | 9 |
| 銷售2部 | 1002 | 2024/5/13 | 9 | 8 |
| 銷售2部 | 1002 | 2024/5/24 | 24 | 22 |
| 銷售2部 | 1002 | 2024/5/25 | 22 | 11 |
| 銷售2部 | 1003 | 2024/5/9 | 50 | 8 |
| 銷售2部 | 1003 | 2024/5/15 | 8 | 7 |
| 銷售3部 | 1001 | 2024/5/2 | 18 | 13 |
| 銷售3部 | 1001 | 2024/5/9 | 13 | 5 |
| 銷售3部 | 1003 | 2024/5/17 | 24 | 21 |
| 銷售3部 | 1003 | 2024/5/21 | 23 | 19 |
| 銷售3部 | 1003 | 2024/5/22 | 19 | 18 |
| 銷售3部 | 1003 | 2024/5/23 | 18 | 12 |
| 銷售3部 | 1003 | 2024/5/26 | 30 | 16 |
+-------+--------+-----------+------+------------+------+------+--------+