如何区分row_number()、rank()和dense_rank()函数
ROW_NUMBER()、RANK()和DENSE_RANK()是MySQL中的窗口函数,它们都用于在查询结果中执行计算和聚合操作,并在每个结果行上产生一个值。虽然它们都用于对数据进行排序和排名,但它们之间有一些区别。
ROW_NUMBER()
ROW_NUMBER()函数为结果集中的每一行分配一个唯一的行号。它不会对排序顺序进行任何间隙处理,为所有行分配连续的行号。即使有两行的排序值相同,它们也会得到不同的行号。
例如,假设我们有一个名为"employees"的表,其中包含员工的信息,如员工ID(ID)、姓名(name)、工资(salary)和雇佣日期(hire_date)。我们希望根据工资对员工进行排序,并为每个员工分配一个行号。
此表为employees的数据表
使用ROW_NUMBER()函数,我们可以这样写查询:
SELECT ROW_NUMBER() OVER (ORDER BY salary DESC) AS row_num, ID, name, salary, hire_date
FROM employees;
执行此查询后,我们将得到一个结果集,其中包含每个员工的行号(row_num)、员工ID、姓名、工资和雇佣日期。行号将根据工资进行降序排序,即使有两名员工的工资相同,他们也会得到不同的行号。
RANK()
RANK()函数与ROW_NUMBER()类似,也是为结果集中的每一行分配一个唯一的排名值。然而,RANK()会处理排序顺序之间的间隙,为每个排名分配连续的整数值。这意味着如果有并列排名的情况,RANK()函数将为并列排名分配相同的排名值,并且下一个排名值将跳过并列排名的数量。
继续上面的例子,使用RANK()函数进行查询:
SELECT RANK() OVER (ORDER BY salary DESC) AS ranks, ID, name, salary, hire_date
FROM employees;
执行此查询后,我们将得到一个结果集,其中包含每个员工的排名值(ranks)、员工ID、姓名、工资和雇佣日期。排名值将根据工资进行降序排序,如果有并列排名的情况,它们将分配相同的排名值,并且下一个排名值将跳过并列排名的数量。
DENSE_RANK()
DENSE_RANK()函数也与ROW_NUMBER()类似,为结果集中的每一行分配一个唯一的排名值。不同之处在于,DENSE_RANK()不会处理排序顺序之间的间隙,而是将每个排名分配连续的整数值。这意味着如果有并列排名的情况,DENSE_RANK()将为并列排名分配相同的排名值,但下一个排名值不会跳过并列排名的数量。
继续上面的例子,使用DENSE_RANK()函数进行查询:
SELECT DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_ranks, ID, name, salary, hire_date
FROM employees;
执行此查询后,我们将得到一个结果集,其中包含每个员工的密度排名值(dense_ranks)、员工ID、姓名、工资和雇佣日期。密度排名值将根据工资进行降序排序,如果有并列排名的情况,它们将分配相同的排名值,但下一个排名值不会跳过并列排名的数量。