Leetcode178.分数排名(中等)

题目
编写一个 SQL 查询来实现分数排名。

如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。

+----+-------+
| Id | Score |
+----+-------+
| 1  | 3.50  |
| 2  | 3.65  |
| 3  | 4.00  |
| 4  | 3.85  |
| 5  | 4.00  |
| 6  | 3.65  |
+----+-------+

例如,根据上述给定的 Scores 表,你的查询应该返回(按分数从高到低排列):

+-------+------+
| Score | Rank |
+-------+------+
| 4.00  | 1    |
| 4.00  | 1    |
| 3.85  | 2    |
| 3.65  | 3    |
| 3.65  | 3    |
| 3.50  | 4    |
+-------+------+

重要提示:对于 MySQL 解决方案,如果要转义用作列名的保留字,可以在关键字之前和之后使用撇号。例如 Rank

审题
这个题目其实就是对得分Score进行排序,且同薪同名且总排名连续,同样的薪水排名结果为1-2-2-3。
得到的结果为Score Rank两列,且按Score进行降序。

自己的解答
其实在做之前的时候已经得到过分数排名的,只不过是对分数进行了去重。在此基础上和Scores表进行内连接然后按Score排序就可以得到最终的结果,但是这样的想法比较简单,但是感觉效率不高。

自己生成表与数据

CREATE TABLE Scores(
Id INT,
Score FLOAT);

INSERT INTO Scores(Id, Score) VALUE(1, 3.5),(2,3.65),(3,4.0),(4,3.85),(5,4.0),(6,3.65);

SELECT * FROM Scores;

回顾一下之前是怎么得到排名的
1.两表自连接,连接条件设定为表1的score小于等于表2的score
2.以表1的score分组,统计表1中每个salary分组后对应表2中score唯一值个数

SELECT S1.`Score`, COUNT(DISTINCT S2.`Score`) as `Rank`
FROM Scores AS S1
JOIN Scores AS S2
ON S1.`Score` <= S2.`Score`
GROUP BY S1.Score;

下面构造内连接即可

SELECT tmp.*
FROM Scores
JOIN (SELECT S1.`Score`, COUNT(DISTINCT S2.`Score`) as `Rank`
    FROM Scores AS S1
    JOIN Scores AS S2
    ON S1.`Score` <= S2.`Score`
    GROUP BY S1.Score) as `tmp`
ON Scores.`Score` = tmp.Score
ORDER BY tmp.Score DESC;

提交成功



好像还不算太慢

注意点
由于Rank为关键字,所以必须 用` `

而且定义变量的方法也是可行的(177提到过)

SELECT @r:=IF(@p=score, @r, @r+1) AS `rank`,  @p:= score AS Score
FROM Scores, (SELECT @r:=0, @p:=NULL)init 
ORDER BY score DESC;

子查询调换一下列即可

# Write your MySQL query statement below
SELECT tmp.Score, tmp.`rank`
FROM (SELECT @r:=IF(@p=score, @r, @r+1) AS `rank`,  @p:= score AS Score
FROM Scores, (SELECT @r:=0, @p:=NULL)init 
ORDER BY score DESC) AS tmp;

额。。。 我觉着没啥问题吧
要不就两列合并算了

SELECT S.`Score`, tmp.`rank`
FROM Scores AS S, 
(SELECT @r:=IF(@p=score, @r, @r+1) AS `rank`,  @p:= score AS Score
FROM Scores, (SELECT @r:=0, @p:=NULL)init 
ORDER BY score DESC) AS tmp;

这样得到的笛卡尔乘积,跪了。。

别的思路与解答
1.子查询
分成两个部分写会容易很多

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

2.利用窗口函数
图解SQL面试题:经典排名问题


对以上数据应用窗口函数
1.涉及到排名问题,可以使用窗口函数
2.专用窗口函数rank, dense_rank, row_number有什么区别呢?

它们的区别我举个例子,你们一下就能看懂:

select *,
   rank() over (order by 成绩 desc) as ranking,
   dense_rank() over (order by 成绩 desc) as dese_rank,
   row_number() over (order by 成绩 desc) as row_num
from 班级

结果如下


  • ranking 得到的排名是有间隔的
  • dese_rank 得到的排名是没有间隔的,也就是我们想要的结果
  • row_num 不管重复数据 就是给定行号
select score, 
       dense_rank() over(order by Score desc) as Rank
from Scores;

3.两表自连接
和我的方法类似 但不用再次联结了 也是1的外连接版本 1是3的子查询版本
按Id和Score分组。每组中,大于等于每个Score的不同Score数目就是其排名。

select S1.Score,count(distinct S2.Score) as `Rank`
from Scores as S1 join Scores as S2 on (S1.Score <= S2.Score)
group by S1.Id,S1.Score
order by S1.Score desc;
  • 为什么要加 group by S1.Id?
    因为要对表中每个数据进行排名 不然结果就是最小的一个

4.对1可以进行优化
把两表联结中的S2表改变一下,不要用所有的数据,而是去重之后再用

SELECT 
  S1.Score,
  COUNT(DISTINCT S2.Score) AS `Rank` 
FROM
  Scores AS S1 
  JOIN 
    (SELECT DISTINCT 
      Score 
    FROM
      Scores 
    ORDER BY Score DESC) AS S2 
    ON (S1.Score <= S2.Score) 
GROUP BY S1.Id, S1.Score 
ORDER BY S1.Score DESC ;

效率确实高一些吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352