SQL语句的排序问题

177.第N高薪水

排名是数据库中的一个经典题目,实际上又根据排名的具体细节可分为3种场景:

1. 连续排名,例如薪水3000、2000、2000、1000排名结果为1-2-3-4,体现同薪不同名,排名类似于编号
2. 同薪同名但总排名不连续,例如同样的薪水分布,排名结果为1-2-2-4
3. 同薪同名且总排名连续,同样的薪水排名结果为1-2-2-3

不同的应用场景可能需要不同的排名结果,也意味着不同的查询策略。
本题的目标是实现第三种排名方式下的第N个结果,且是全局排名,不存在分组的问题,相对简单一些。
图片说明

思路一:单表查询: ORDER BY + LIMIT

由于本题不存在分组排序,只需返回全局第N高的一个,所以自然想到的想法是用order by排序加limit限制得到。需要注意两个细节:

- 同薪同名且不跳级的问题,解决办法是用group by按薪水分组后再order by
- 排名第N高意味着要跳过N-1个薪水,由于无法直接用limit N-1,所以需先在函数开头处理N为N=N-1。

注:这里不能直接用limit N-1是因为limit和offset字段后面只接受正整数(意味着0、负数、小数都不行)或者单一变量(意味着不能用表达式),也就是说想取一条,limit 2-1、limit 1.1这类的写法都是报错的。
注:这种解法形式最为简洁直观,但仅适用于查询全局排名问题,如果要求各分组的每个第N名,则该方法不适用;而且也不能处理存在重复值的情况。

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
    SET N := N-1;//注意:LIMIT 中不能做运算,故在RETURN前运算
  RETURN (
      # Write your MySQL query statement below.
      SELECT 
            salary
      FROM 
            employee
      GROUP BY 
            salary
      ORDER BY 
            salary DESC
      LIMIT N, 1
  );
END

使用 IFNULL

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN

  SET N = N -1;
  RETURN (
      # Write your MySQL query statement below.
      SELECT ifnull(
          (SELECT DISTINCT salary
          FROM Employee
          ORDER BY salary desc
          LIMIT N , 1) , null
      ) AS getNthHighestSalary
  );

END

178.分数排名

图片说明
图片说明

思路

比如你考了98分,,你同学a也考了98分,找到大于等于你的成绩,一个99分,一个98分,一个98分,去重复,就一个99,一个98,count一下总数,第二名,如果有三个同学考了97呢,同理,99,98,98,97,97,97 后面比这个少的,已经死在了筛选条件,去重,99,98,97,count=3

select a.Score as Score,
(select count(distinct b.Score) from Scores b where b.Score >= a.Score) as 'Rank'
from Scores a
order by a.Score DESC
//MySql8中自带RANK()函数,故Rank字段需要加‘’
//函数dense_rank()的使用
SELECT Score,
dense_rank() over(order by Score desc) as 'Rank'
FROM Scores 

row_number()、rank()、dense_rank()函数的区别

  1. row_number()与rank()
    图片说明
  2. rank()与dense_rank()
    图片说明
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务