题目链接:https://leetcode-cn.com/problems/rank-scores/

题目

编写一个 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 |

+-------+------+

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/rank-scores

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解答

使用 oracle 或者 hive 的开窗函数,直接实现。

---- oracle ----
/* Write your PL/SQL query statement below */
select Score,
dense_rank() over(order by Score desc) as Rank
from Scores; ---- 473ms

这么简单,不应该是中等难度的题目啊。。

不过 MySQL 中没有这种语法,学习一下应该如何实现?

学习一下大神的解法。

  • 如果通过子查询的方法来排序求行号,扫描成本 N*N
  • 使用 cross join 对一个行表进行关联,成本依旧很高
  • 使用 select @a := 0 产生只有一行的数据,扫描全表
---- MySQL ----
select score,
@a := @a + 1 as rank
from scores,
(select @a := 0) t
order by score desc;
-- 实现排序

针对相同的分数需要处理成相同的排名,所以需要添加辅助变量

@a := @a + (分数是否相同?0:1)
@a := @a + (@pre <> (@pre := score))

最终脚本,牛逼!

---- MySQL ----
select Score,
@a := @a + (@pre <> (@pre := Score)) as rank
from Scores,
(select @a := 0,
@pre := -1) t
order by Score desc; ---- 138ms

解释一下:

  1. @a 类似在 Oracle 中的rownum,可以在生成结果内附加上一列序列号,可以近似理解为查询后加上行号;
  2. @a := @a + 1 实际上是赋值,旧值+1变为新值赋给@a
  3. 实际上并没有直接 @a+1 那么简单,还要先去判断分数是否与前一行相同,所以引入 @pre 来记录:
    • 先将Score赋值给: @pre := Score
    • 然后判断之前的 @pre 是否与赋值后的 @pre 不相同 ==> (@pre <> (@pre := Score)) “<>” 就是 "!=" 的意思;
    • 两者不同,判断结果为真,则取1; 两者相同,判断结果为假,取0, 最后再用 0或1 加上 @a 即为当前行分数的排名;
  4. (select @a := 0, @pre := -1) t 为初始化 @a@pre 的开始值;
    • @pre 初始值为 -1 为的是防止Score有 0 分的出现;
    • @第一次比较Score值的时候,@pre初始值肯定和Score不同, 所以第一次比较 @a 必然会 +1,所以@a要从0开始;
  5. 最后以将结果根据 Score 进行倒序展示;
  6. 顺便一提的是,这个代码的结果生成的rank带有小数点,可以考虑使用 cast() 方法来消除排名的小数点;

另一种,比较一般的解法。

---- MySQL ----
# Write your MySQL query statement below
select a.Score,
(select count(distinct b.Score)
from Scores b
where b.Score > a.Score) + 1 as rank
from Scores a
order by Score desc; ---- 605ms

自连接的解法速度比较慢。

思考

区分对比一下几个排序函数 row_number()rank()dense_rank()ntile() 的区别。

MySQL 中可以使用变量的方式进行求解。

LeetCode:178.分数排名的更多相关文章

  1. SQL Server实现 LeetCode 178 分数排名

    178. 分数排名 SQL架构 编写一个 SQL 查询来实现分数排名.如果两个分数相同,则两个分数排名(Rank)相同.请注意,平分后的下一个名次应该是下一个连续的整数值.换句话说,名次之间不应该有& ...

  2. LeetCode 178. 分数排名

    1.题目描述 编写一个 SQL 查询来实现分数排名.如果两个分数相同,则两个分数排名(Rank)相同.请注意,平分后的下一个名次应该是下一个连续的整数值.换句话说,名次之间不应该有“间隔”. +--- ...

  3. 178. 分数排名 + MySql + RANK() OVER

    178. 分数排名 LeetCode_MySql_178 题目描述 题解分析 排名函数 DENSE_RANK().如果使用 DENSE_RANK() 进行排名会得到:1,1,2,3,4. RANK() ...

  4. LeetCode(数据库):分数排名

    ,)); Truncate table Scores; ', '3.5'); ', '3.65'); ', '4.0'); ', '3.85'); ', '4.0'); ', '3.65'); 编写一 ...

  5. sql 178. 分数排名

    编写一个 SQL 查询来实现分数排名.如果两个分数相同,则两个分数排名(Rank)相同.请注意,平分后的下一个名次应该是下一个连续的整数值.换句话说,名次之间不应该有“间隔”. +----+----- ...

  6. [SQL]LeetCode178. 分数排名 | Rank Scores

    Write a SQL query to rank scores. If there is a tie between two scores, both should have the same ra ...

  7. MYSQL分数排名

    编写一个 SQL 查询来实现分数排名.如果两个分数相同,则两个分数排名(Rank)相同.请注意,平分后的下一个名次应该是下一个连续的整数值.换句话说,名次之间不应该有“间隔”. +----+----- ...

  8. mysql查询之分数排名

    编写一个 SQL 查询来实现分数排名.如果两个分数相同,则两个分数排名(Rank)相同 +----+-------+ | Id | Score | +----+-------+ | 1 | 3.50 ...

  9. Django项目:CRM(客户关系管理系统)--75--65PerfectCRM实现CRM课程分数排名

    # classtop_urls.py # ————————64PerfectCRM实现CRM课程排名详情———————— from django.conf.urls import url from b ...

随机推荐

  1. maven打包遇到错误,Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.22.1:test

    对Pom文件进行配置(亲自尝试,已成功解决) <build> <plugins> <plugin> <groupId>org.apache.maven. ...

  2. JAVA通过FTP方式向远程服务器或者客户端上传、下载文件,以及删除FTP服务器上的文件

    1.在目标服务器上搭建FTP服务器 搭建方式有多种大家可以自行选择,例如使用Serv-U或者FTPServer.exe:这里我以FTPServer.exe为例搭建:在目标服务器(这里对应的IP是10. ...

  3. MySQL 慢查询日志介绍

    转: MySQL 慢查询日志介绍 2018年08月23日 08:47:40 曾梦想仗剑走天涯XX 阅读数 1104   一. 慢查询介绍 MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记 ...

  4. eclipse、MyEclipse 修改字符集和JDK

    eclipse 中UTF-8设置 1.windows->Preferences   打开"首选项"对话框: 2.然后,general->Workspace,右 侧Tex ...

  5. scikit-learn机器学习(一)简单线性回归

    # -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt ## 设置字符集,防止中文乱码 import ma ...

  6. 20190615 NACE关于采购订单的输出类型

    项目已经做好的配置,我们复盘一下 一.使用NACE 进入输出控制条件: EF 采购订单,首先看->输出类型 标准是使用 nast 作为记录表 1输出类型, 2过程, 3 存取顺序,4 条件记录: ...

  7. Data - 数据挖掘的基础概念

    主要内容来自于<微信公众号:程SIR说> 1 数据挖掘 数据挖掘(Data Mining,简称DM),是指从大量的数据中,挖掘出未知的且有价值的信息和知识的过程. 数据挖掘是一门交叉学科, ...

  8. rabbitmq-BasicReject

    拒收,是接收端在收到消息的时候响应给RabbitMQ服务的一种命令,告诉服务器不应该由我处理,或者拒绝处理,扔掉.接收端在发送reject命令的时候可以选择是否要重新放回queue中.如果没有其他接收 ...

  9. Chrome安装json格式化工具jsonView

    1.下载jsonView 有条件的童鞋可以去谷歌商店下载安装https://chrome.google.com/webstore/detail/pmajcnnfhjcebiafkonednglookd ...

  10. 【FFMPEG】【ARM-Linux开发】 ffmpeg 静态库使用,undefined reference错误

    原文:http://blog.csdn.net/chinazjn/article/details/7954984 ffmpeg移植到dm365上,遇到undefined reference错误: GA ...