MySQL 8.0 前無 ROW_NUMBER() 窗口函數,需用用戶變數模擬排名功能。
-- 1. 初始化變數 SET @rank = 0; -- 2. 查詢中遞增 SELECT @rank := @rank + 1 AS rank, column1, column2 FROM table_name ORDER BY sort_column;
-- 建表測試
CREATE TABLE students (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20),
score INT
);
INSERT INTO students (name, score) VALUES
('Alice', 95), ('Bob', 87), ('Charlie', 92), ('David', 87), ('Eve', 98);
-- 排名查詢(分數降序,同分同排名?需進階邏輯)
SET @rank = 0;
SET @prev_score = NULL;
SET @real_rank = 0;
SELECT
@real_rank := IF(@prev_score = score, @real_rank, @rank) AS rank,
@rank := @rank + 1 AS row_num,
@prev_score := score AS score,
name
FROM students
ORDER BY score DESC;
+------+---------+-------+--------+ | rank | row_num | score | name | +------+---------+-------+--------+ | 1 | 1 | 98 | Eve | | 2 | 2 | 95 | Alice | | 3 | 3 | 92 | Charlie| | 4 | 4 | 87 | Bob | | 4 | 5 | 87 | David | +------+---------+-------+--------+
SET @rank = 0; SET @prev = NULL;
SELECT
@rank := IF(@prev = score, @rank, @rank + 1) AS dense_rank,
@prev := score AS score,
name
FROM students ORDER BY score DESC;
SET @rank = 0; SET @row = 0; SET @prev = NULL;
SELECT
@rank := IF(@prev = score, @rank, @row + 1) AS competition_rank,
@row := @row + 1 AS row_num,
@prev := score AS score,
name
FROM students ORDER BY score DESC;
SET @rank = 0; SET @prev_class = NULL; SET @prev_score = NULL;
SELECT
@rank := IF(@prev_class = class AND @prev_score = score, @rank,
IF(@prev_class = class, @rank + 1, 1)) AS class_rank,
@prev_class := class AS class,
@prev_score := score AS score,
name
FROM students
ORDER BY class, score DESC;
-- 標準語法,效能更好、語意清晰
SELECT
name, score,
ROW_NUMBER() OVER (ORDER BY score DESC) AS row_num,
RANK() OVER (ORDER BY score DESC) AS competition_rank,
DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rank,
PERCENT_RANK() OVER (ORDER BY score DESC) AS percent_rank
FROM students;
ORDER BY 必須在變數計算之前,子查詢包裹確保順序SET @var = 0,否則殘留值導致錯誤CREATE TABLE t2 SELECT @rank:=@rank+1 ... 結果不可預測