需求中有一点这样的功能,我这边在本地 mysql 做了实现并测试,发现如果自己写基本上跑不出来 10 万条数据,但是使用 mysql8 中自带的窗口函数就会非常之快。
首先需要讲一下,排名结果大致分为两种,一种是排名连续,另外一种是排名不连续。例如有三个同学 A B C,A100分,B100分,C90分,那么在排名连续的情况下,A和B都是第一名,C是第二名;如果是排名不连续的情况下,A和B同样的,都是第一名,但是C是第三名。
1. 子查询实现
tips: 无法跑通 10 万条数据
-- 1. 排名不中断
SELECT
a.score,
(
SELECT count( DISTINCT b.score ) + 1
FROM scores b WHERE b.score > a.score
) AS 'rank'
FROM
scores a
ORDER BY
score DESC;
-- 2. 排名中断
SELECT
a.score,
(
SELECT count( 1 ) + 1
FROM scores b WHERE b.score > a.score
) AS 'rank'
FROM
scores a
ORDER BY
score DESC;
2. 使用窗口函数(mysql8)
tips:平均用时0.28秒,非常之快!
-- 1. 排名中断
SELECT
score
RANK() over ( ORDER BY score DESC ) AS 'rank'
FROM
scores;
-- 2. 排名连续
SELECT
score,
DENSE_RANK() over ( ORDER BY score DESC ) AS 'rank'
FROM
scores;
以上测试的结果供大家参考,如果数据量大的话,需要使用 sql 中将排名查出来,建议最好使用窗口函数。