虽然我没有足够的声誉点来评论(有点幽默),但 MySQL 近年来已经取得了长足的进步。添加了窗口函数和 CTE(WITH 子句),这意味着现在支持 rank(和 row_number 等)。
我是同一个“乔恩·阿姆斯特朗 - Xgc”,但那个帐户在旧电子邮件地址的风中丢失了。
一条评论提出了一个关于 MySQL 是否支持排名窗口函数的问题。回答:是的。
几年前我的原始回复:
SELECT p1.student_id
, p1.class_id
, p1.grade
, COUNT(p2.student_id) AS rank
FROM grades AS p1
JOIN grades AS p2
ON (p2.grade, p2.student_id) >= (p1.grade, p1.student_id)
AND p1.class_id = p2.class_id
GROUP BY p1.student_id, p1.class_id
ORDER BY p1.class_id, rank
;
结果:
+------------+----------+-------+------+
| student_id | class_id | grade | rank |
+------------+----------+-------+------+
| 2 | 1 | 99 | 1 |
| 1 | 1 | 90 | 2 |
| 3 | 1 | 80 | 3 |
| 4 | 1 | 70 | 4 |
| 6 | 2 | 90 | 1 |
| 1 | 2 | 80 | 2 |
| 5 | 2 | 78 | 3 |
| 7 | 3 | 90 | 1 |
| 6 | 3 | 50 | 2 |
+------------+----------+-------+------+
9 rows in set (0.001 sec)
使用 ROW_NUMBER 窗口函数:
WITH cte1 AS (
SELECT student_id
, class_id
, grade
, ROW_NUMBER() OVER (PARTITION BY class_id ORDER BY grade DESC) AS rank
FROM grades
)
SELECT *
FROM cte1
ORDER BY class_id, r
;
结果:
+------------+----------+-------+------+
| student_id | class_id | grade | rank |
+------------+----------+-------+------+
| 2 | 1 | 99 | 1 |
| 1 | 1 | 90 | 2 |
| 3 | 1 | 80 | 3 |
| 4 | 1 | 70 | 4 |
| 6 | 2 | 90 | 1 |
| 1 | 2 | 80 | 2 |
| 5 | 2 | 78 | 3 |
| 7 | 3 | 90 | 1 |
| 6 | 3 | 50 | 2 |
+------------+----------+-------+------+
9 rows in set (0.002 sec)
使用 RANK 窗口函数:
WITH cte1 AS (
SELECT student_id
, class_id
, grade
, RANK() OVER (PARTITION BY class_id ORDER BY grade DESC) AS rank
FROM grades
)
SELECT *
FROM cte1
ORDER BY class_id, rank
;
结果:
+------------+----------+-------+------+
| student_id | class_id | grade | rank |
+------------+----------+-------+------+
| 2 | 1 | 99 | 1 |
| 1 | 1 | 90 | 2 |
| 3 | 1 | 80 | 3 |
| 4 | 1 | 70 | 4 |
| 6 | 2 | 90 | 1 |
| 1 | 2 | 80 | 2 |
| 5 | 2 | 78 | 3 |
| 7 | 3 | 90 | 1 |
| 6 | 3 | 50 | 2 |
+------------+----------+-------+------+
9 rows in set (0.000 sec)