mysql 排名函数 rank rownumber 等区别

mysql 排名函数 rank rownumber 等区别

在 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(): 在重复值时给予相同的排名,但不跳过后续的排名。

选择哪个函数取决于你的具体需求,比如是否需要处理重复值以及是否希望排名中出现跳跃。