MySQL數據表結構
創建 tbl_class_info 表,表中有四個字段 id、username、score、group_name
使用?ROW_NUMBER()、DENSE_RANK() 查詢每組前三名
-- 查詢每組前3名
SELECT username, score, group_name
FROM ( SELECT username, score, group_name, ROW_NUMBER() OVER (PARTITION BY group_name ORDER BY score DESC) AS test_rank,DENSE_RANK() OVER (PARTITION BY group_name ORDER BY score DESC) AS test_dense_rank FROM tbl_class_info
) AS ranked_scores
WHERE test_rank <= 3 OR test_dense_rank <= 3
查詢結果:
使用?ROW_NUMBER()、DENSE_RANK() 查詢第二名
-- 查詢每組第2名
SELECT username, score, group_name
FROM ( SELECT username, score, group_name, ROW_NUMBER() OVER (PARTITION BY group_name ORDER BY score DESC) AS test_rank FROM tbl_class_info
) AS ranked_scores
WHERE test_rank = 2
查詢結果:
使用 ROW_NUMBER()、DENSE_RANK() 查詢結果是不同的,
ROW_NUMBER()和DENSE_RANK()是常見的窗口函數,它們可以用于對結果集中的行進行排序和編號,它們的主要區別在于?使用DENSE_RANK()函數為每個組(group_name
)中的記錄根據成績(score
)降序排列,并為每組中的行分配一個唯一的序號(rank
)。
與ROW_NUMBER()不同,如果存在相同的成績,DENSE_RANK()會為它們分配連續的序號,而不會跳過任何數字。下面是實例說明:
ROW_NUMBER()、DENSE_RANK() 區別詳解
使用ROW_NUMBER()查詢數據:
SELECTusername,score,group_name,ROW_NUMBER() OVER (PARTITION BY group_name
ORDER BYscore DESC) AS rank_number
FROMtbl_class_info;
執行結果可以看到,即使成績(score)相同,rank_number 序號也是不同的
使用 DENSE_RANK() 查詢數據:
SELECTusername,score,group_name,DENSE_RANK() OVER (PARTITION BY group_name
ORDER BYscore DESC) AS rank_number
FROMtbl_class_info;
執行結果可以看到,即使成績(score)相同,rank_number 序號也是相同的
所以總的來說,ROW_NUMBER() 和 DENSE_RANK() 都是非常有用的窗口函數,它們可以用于各種數據分析任務。但是,它們之間的區別意味著它們適用于不同的場景。如果您需要為每個行分配唯一的數字,即使在有重復值的情況下也是如此,那么 ROW_NUMBER() 是更好的選擇。如果您需要為每個行分配唯一的數字,但如果有重復值,則需要跳過重復值,那么 DENSE_RANK() 是更好的選擇。
MySQL窗口函數的使用語法
SELECT <窗口函數> OVER ([PARTITION BY <表達式>][ORDER BY <表達式>][ROWS BETWEEN <表達式> AND <表達式>]
)
FROM <表名>
?其中:?
- <窗口函數> ?是窗口函數的名稱。?
- PARTITION BY <表達式> ?是分區表達式。分區表達式用于將表中的行分成多個分區。?
- ORDER BY <表達式> ?是排序表達式。排序表達式用于對分區中的行進行排序。?
- ROWS BETWEEN <表達式> AND <表達式> ?是行范圍表達式。行范圍表達式用于指定窗口函數計算的行的范圍。
SELECTgroup_name,AVG(score) OVER (PARTITION BY group_name
ORDER BYscore DESC ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS avg_sales
FROMtbl_class_info;
執行結果:
注:在窗口函數中,ROWS BETWEEN <表達式> AND <表達式> 用于指定窗口的邊界范圍。這個范圍是根據指定的表達式來確定的。通常,第一個表達式指定了窗口的起始行,第二個表達式指定了窗口的結束行。
在計算窗口函數之前,數據庫會先確定窗口的范圍。然后,根據指定的窗口范圍,對范圍內的行進行運算。通常,窗口函數會對窗口內的每一行執行計算,并返回一個與窗口范圍相對應的結果。
?
MySQL中常見的窗口函數有哪些
? SUM()函數:計算指定列的總和。
SELECT column1, SUM(column2) OVER (PARTITION BY column1) AS total_sum
FROM table;
? AVG()函數:計算指定列的平均值。
SELECT column1, AVG(column2) OVER (PARTITION BY column1) AS average_value ?
FROM table;
? MIN()函數:返回指定列的最小值。
SELECT column1, MIN(column2) OVER (PARTITION BY column1) AS minimum_value ?
FROM table;
? MAX()函數:返回指定列的最大值。
SELECT column1, MAX(column2) OVER (PARTITION BY column1) AS maximum_value ?
FROM table;
? COUNT()函數:計算指定列的非空值的數量。
SELECT column1, COUNT(column2) OVER (PARTITION BY column1) AS count_value ?
FROM table;
? RANK()函數:返回一組行的排名。
SELECT column1, RANK() OVER (ORDER BY column2 DESC) AS rank_value ?
FROM table;
? DENSE_RANK()函數:返回一組行的不間斷排名。
SELECT column1, DENSE_RANK() OVER (ORDER BY column2 DESC) AS dense_rank_value ?
FROM table;
? ROW_NUMBER()函數:為一組行分配一個唯一的數字。
SELECT column1, ROW_NUMBER() OVER (PARTITION BY column1 ORDER BY column2 DESC) AS row_number_value ?
FROM table;
MySQL窗口函數和聚合函數的區別
窗口函數和聚合函數都是在數據庫中對數據進行計算的函數。但是,它們之間有一些關鍵區別。?
- 窗口函數返回一個單個值,該值是基于一組行計算的。這組行稱為窗口。窗口函數可以使用窗口中的所有行,也可以使用窗口中的部分行。?
- 聚合函數返回一個單個值,該值是基于整個表中的數據計算的。聚合函數不能使用窗口,因為它們需要訪問整個表的數據才能計算結果。?
SELECT SUM(sales) FROM orders;SELECT SUM(sales) OVER (PARTITION BY product_id ORDER BY order_date);
第一個查詢使用聚合函數 SUM 計算整個表中所有訂單的總銷售額。
第二個查詢使用窗口函數 SUM 計算每個產品的總銷售額。窗口函數 SUM 使用 ORDER BY 子句對訂單按日期排序,然后計算每個產品的總銷售額。?
窗口函數和聚合函數都是在數據庫中對數據進行計算的強大工具。但是,它們之間有一些關鍵區別,因此在選擇使用哪種函數時需要考慮這些區別。