在 MySQL 8.0 及以后版本中,窗口函數(Window Functions)為數據分析和處理提供了強大的工具。窗口函數允許在查詢結果集上執行計算,而不必使用子查詢或連接,這使得某些類型的計算更加高效和簡潔。
語法結構
function_name() OVER ([PARTITION BY expression_list][ORDER BY expression_list][frame_clause]
)
- PARTITION BY:將查詢結果集分成多個分區,類似于 GROUP BY,但在窗口函數中是用于定義數據的分組邏輯。例如,按照部門分區,然后在每個部門內進行操作。
- ORDER BY:對每個分區內的行進行排序,這是可選的。窗口函數的計算可能會依賴于行的順序,如計算累計和等。
創建測試表
CREATE TABLE `employee` (`employee_id` int NOT NULL AUTO_INCREMENT,`department` varchar(45) DEFAULT NULL,`salary` varchar(45) DEFAULT NULL,PRIMARY KEY (`employee_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
寫入測試數據
INSERT INTO `test`.`employee` (`employee_id`, `department`, `salary`) VALUES (1, 'Sales', '6000');
INSERT INTO `test`.`employee` (`employee_id`, `department`, `salary`) VALUES (2, 'Sales', '6000');
INSERT INTO `test`.`employee` (`employee_id`, `department`, `salary`) VALUES (3, 'Sales', '5000');
INSERT INTO `test`.`employee` (`employee_id`, `department`, `salary`) VALUES (4, 'IT', '7000');
INSERT INTO `test`.`employee` (`employee_id`, `department`, `salary`) VALUES (5, 'IT', '9000');
INSERT INTO `test`.`employee` (`employee_id`, `department`, `salary`) VALUES (6, 'Marketing', '5500');
INSERT INTO `test`.`employee` (`employee_id`, `department`, `salary`) VALUES (7, 'Sales', '5000');
使用窗口函數
SELECT employee_id, department, salary,
RANK() OVER (PARTITION BY department ORDER BY salary desc) AS ran,
DENSE_RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS d_ran,
ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS row_num
FROM employee;
RANK() 函數計算排名,如果有并列情況,排名會出現跳躍。
DENSE_RANK() 函數在并列情況下不會跳躍。
ROW_NUMBER() 函數為每一行分配一個唯一的行號,即使有并列情況也是如此。
實際使用時,可以通過結合cte表達式,指定row_num值,來實現數據去重的效果。
例如:
with distinct_tbl as (select *,ROW_NUMBER() OVER (PARTITION BY department,salary ORDER BY salary DESC) AS row_numfrom employee
)
select * from distinct_tbl
where row_num = 1
執行結果