
在 MySQL 中,处理排名相关的需求时,你可能会遇到 RANK(), DENSE_RANK(), 和 ROW_NUMBER() 这几个函数。虽然它们都用于生成行号或排名,但它们在处理重复值时的行为有所不同。以下是这些函数的详细解释和区别:
1. ROW_NUMBER()
ROW_NUMBER() 函数为结果集中的每一行分配一个唯一的序号,这个序号是连续的,不会因为值的重复而改变。
语法:
ROW_NUMBER() OVER ([PARTITION BY partition_expression, ...] ORDER BY sort_expression [ASC|DESC], ...)特点:
- 每行的编号是唯一的,即使两行有相同的排序值。
- 不会跳过任何数字。
示例: 假设有一个包含学生成绩的表 students,我们想要按成绩对学生进行排名:
SELECT student_id, score, ROW_NUMBER() OVER (ORDER BY score DESC) AS row_num FROM students;如果两个学生的分数相同,他们将被赋予不同的行号。
2. RANK()
RANK() 函数根据指定的排序条件对结果进行排名,但在出现重复值时,会给予所有重复值相同的排名,并且接下来的排名将跳过相应的数量。
语法:
RANK() OVER ([PARTITION BY partition_expression, ...] ORDER BY sort_expression [ASC|DESC], ...)特点:
- 如果两行有相同的排序值,它们将获得相同的排名。
- 下一个不重复的值的排名将是当前排名加上重复的行数(即会有跳跃)。
示例: 使用同样的 students 表:
SELECT student_id, score, RANK() OVER (ORDER BY score DESC) AS rank FROM students;如果有两名学生并列第一,那么下一名学生将会是第三名。
3. DENSE_RANK()
DENSE_RANK() 函数与 RANK() 类似,也是根据排序条件进行排名,并在出现重复值时给予相同的排名。不过,它不会跳过任何数字。
语法:
DENSE_RANK() OVER ([PARTITION BY partition_expression, ...] ORDER BY sort_expression [ASC|DESC], ...)特点:
- 如果两行有相同的排序值,它们将获得相同的排名。
- 下一个不重复的值的排名是当前排名加1(不会有跳跃)。
示例: 使用同样的 students 表:
SELECT student_id, score, DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rank FROM students;如果有两名学生并列第一,那么下一名学生将会是第二名。
总结
- ROW_NUMBER(): 为每行分配一个连续的唯一序号。
- RANK(): 在重复值时给予相同的排名,并跳过相应数量的后续排名。
- DENSE_RANK(): 在重复值时给予相同的排名,但不跳过后续的排名。
选择哪个函数取决于你的具体需求,比如是否需要处理重复值以及是否希望排名中出现跳跃。
