在MySQL中实现Rank高级排名函数【转】
MySQL中没有Rank排名函数,当我们需要查询排名时,只能使用MySQL数据库中的基本查询语句来查询普通排名。尽管如此,可不要小瞧基础而简单的查询语句,我们可以利用其来达到Rank函数一样的高级排名效果。
在这里我用一个简单例子来实现排名的查询:
首先我们先创建一个我们需要进行高级排名查询的players表,
CREATE TABLE `players` (
`pid` int(2) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`age` int(2) NOT NULL,
PRIMARY KEY (`pid`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `players` (`pid`, `name`, `age`) VALUES
(1, 'Samual', 25),
(2, 'Vino', 20),
(3, 'John', 20),
(4, 'Andy', 22),
(5, 'Brian', 21),
(6, 'Dew', 24),
(7, 'Kris', 25),
(8, 'William', 26),
(9, 'George', 23),
(10, 'Peter', 19),
(11, 'Tom', 20),
(12, 'Andre', 20);
1、在MySQL中实现Rank普通排名函数
在这里,我们希望获得一个排名字段的列,以及age的升序排列。所以我们的查询语句将是:
SELECT pid, name, age, @curRank := @curRank + 1 AS rank
FROM players p, (
SELECT @curRank := 0
) q
ORDER BY age
| PID | NAME | AGE | RANK |
|-----|---------|-----|------|
| 10 | Peter | 19 | 1 |
| 12 | Andre | 20 | 2 |
| 2 | Vino | 20 | 3 |
| 3 | John | 20 | 4 |
| 11 | Tom | 20 | 5 |
| 5 | Brian | 21 | 6 |
| 4 | Andy | 22 | 7 |
| 9 | George | 23 | 8 |
| 6 | Dew | 24 | 9 |
| 7 | Kris | 25 | 10 |
| 1 | Samual | 25 | 11 |
| 8 | William | 26 | 12 |
要在mysql中声明一个变量,你必须在变量名之前使用@符号。FROM子句中的(@curRank := 0)部分允许我们进行变量初始化,而不需要单独的SET命令。当然,也可以使用SET,但它会处理两个查询:
SET @curRank := 0;
SELECT pid, name, age, @curRank := @curRank + 1 AS rank
FROM players
ORDER BY age
2、查询以降序排列
首要按age的降序排列,其次按name进行排列,只需修改查询语句加上ORDER BY和 DESC以及列名即可。
SELECT pid, name, age, @curRank := @curRank + 1 AS rank
FROM players p, (
SELECT @curRank := 0
) q
ORDER BY age DESC, name
| PID | NAME | AGE | RANK |
|-----|---------|-----|------|
| 8 | William | 26 | 1 |
| 7 | Kris | 25 | 2 |
| 1 | Samual | 25 | 3 |
| 6 | Dew | 24 | 4 |
| 9 | George | 23 | 5 |
| 4 | Andy | 22 | 6 |
| 5 | Brian | 21 | 7 |
| 12 | Andre | 20 | 8 |
| 3 | John | 20 | 9 |
| 11 | Tom | 20 | 10 |
| 2 | Vino | 20 | 11 |
| 10 | Peter | 19 | 12 |
3、在MySQL中实现Rank普通并列排名函数
现在,如果我们希望为并列数据的行赋予相同的排名,则意味着那些在排名比较列中具有相同值的行应在MySQL中计算排名时保持相同的排名(例如在我们的例子中的age)。为此,我们使用了一个额外的变量。
SELECT pid, name, age,
CASE
WHEN @prevRank = age THEN @curRank
WHEN @prevRank := age THEN @curRank := @curRank + 1
END AS rank
FROM players p,
(SELECT @curRank :=0, @prevRank := NULL) r
ORDER BY age
| PID | NAME | AGE | RANK |
|-----|---------|-----|------|
| 10 | Peter | 19 | 1 |
| 12 | Andre | 20 | 2 |
| 2 | Vino | 20 | 2 |
| 3 | John | 20 | 2 |
| 11 | Tom | 20 | 2 |
| 5 | Brian | 21 | 3 |
| 4 | Andy | 22 | 4 |
| 9 | George | 23 | 5 |
| 6 | Dew | 24 | 6 |
| 7 | Kris | 25 | 7 |
| 1 | Samual | 25 | 7 |
| 8 | William | 26 | 8 |
如上所示,具有相同数据和排行的两行或多行,它们都会获得相同的排名。玩家Andre, Vino, John 和Tom都有相同的age,所以他们排名并列第二。下一个最高age的玩家(Brian)排名第3。这个查询相当于MSSQL和ORACLE 中的DENSE_RANK()函数。
4、在MySQL中实现Rank高级并列排名函数
当使用RANK()函数时,如果两个或以上的行排名并列,则相同的行都会有相同的排名,但是实际排名中存在有关系的差距。
SELECT pid, name, age, rank FROM
(SELECT pid, name, age,
@curRank := IF(@prevRank = age, @curRank, @incRank) AS rank,
@incRank := @incRank + 1,
@prevRank := age
FROM players p, (
SELECT @curRank :=0, @prevRank := NULL, @incRank := 1
) r
ORDER BY age) s
这是一个查询中的子查询。我们使用三个变量(@incRank,@prevRank,@curRank)来计算关系的情况下,在查询结果中我们已经补全了因为并列而导致的排名空位。我们已经封闭子查询到查询。这个查询相当于MSSQL和ORACLE中的RANK()函数。
| PID | NAME | AGE | RANK |
|-----|---------|-----|------|
| 10 | Peter | 19 | 1 |
| 12 | Andre | 20 | 2 |
| 2 | Vino | 20 | 2 |
| 3 | John | 20 | 2 |
| 11 | Tom | 20 | 2 |
| 5 | Brian | 21 | 6 |
| 4 | Andy | 22 | 7 |
| 9 | George | 23 | 8 |
| 6 | Dew | 24 | 9 |
| 7 | Kris | 25 | 10 |
| 1 | Samual | 25 | 10 |
| 8 | William | 26 | 12 |
在这里我们可以看到,Andre,Vino,John和Tom都有相同的age,所以他们排名并列第二。下一个最高年龄的球员(Brian)排名第6,而不是第3,因为有4个人并列排名在第2。
好的,我希望在这些例子后,能让你了解RANK()和DENSE_RANK()之间的区别,并且知道在哪里应使用哪个查询来获取MySQL中的rank函数。谢谢。
原文地址: http://fellowtuts.com/mysql/query-to-obtain-rank-function-in-mysql
本文转自简书:在MySQL中实现Rank高级排名函数
在MySQL中实现Rank高级排名函数【转】的更多相关文章
- 在MySQL中实现Rank高级排名函数
MySQL中没有Rank排名函数,当我们需要查询排名时,只能使用MySQL数据库中的基本查询语句来查询普通排名.尽管如此,可不要小瞧基础而简单的查询语句,我们可以利用其来达到Rank函数一样的高级排名 ...
- trim()函数 mysql中的强大字符串过滤函数
mysql中功能强大的trim()函数. 去除两边空格: mysql> select trim(' hello world '); +-----------------------+ | tri ...
- MYSQL中关于日期处理的函数
< DOCTYPE HTML PUBLIC -WCDTD HTML TransitionalEN> MySQL数据库中SQL语句中 关于日期.时间\时间戳的函数 一 MySQL 获得当 ...
- MySQL 中的 FOUND_ROWS() 与 ROW_COUNT() 函数
移植sql server 的存储过程到mysql中,遇到了sql server中的: IF @@ROWCOUNT < 1 对应到mysql中可以使用 FOUND_ROWS() 函数来替换. 1. ...
- MySQL中的内置系统函数
一.字符串函数 1. CONCAT(S1,S2....SN): 把传入的参数连接成一个字符串 2. INSERT(str, x, y, insert): 将字符串 X位置开始,y个字符串长度替换为 ...
- 开发过程中 的一些 补充知识点 + 关于mysql中的日期和时间函数?
参考: https://www.jb51.net/article/23966.htm https://yq.aliyun.com/articles/260389 mysql中的 日期格式是: HHHH ...
- Mysql中的JSON系列操作函数
前言 JSON是一种轻量级的数据交换格式,采用了独立于语言的文本格式,类似XML,但是比XML简单,易读并且易编写.对机器来说易于解析和生成,并且会减少网络带宽的传输. JSON的格式非常简单:名称/ ...
- mysql中返回当前时间的函数或者常量
引用:http://blog.sina.com.cn/s/blog_6d39dc6f0100m7eo.html 1.1 获得当前日期+时间(date + time)函数:now() 除了 now() ...
- SQL中ROW_NUMBER()/RANK() /DENSE_RANK() OVER函数的基本用法
一.ROW_NUMBER()的用法 语法:ROW_NUMBER() OVER(PARTITION BY COLUMN ORDER BY COLUMN) row_number()从1开始,为每一条分组记 ...
随机推荐
- 终于等到你: 图形化开源爬虫Hawk 3发布!
超级图形化爬虫Hawk已经发布两年半时间了,2015年升级到第二版,收到上千条用户反馈(tucao),100多个红包,总共666块五毛~一直想攒着这笔钱,去北境之王天通苑的龙德商场买最心爱的阿迪王! ...
- nginx+php+mysql+wordpress搭建简单站点 安装及配置过程
环境 阿里云ECS云服务器 CPU:1核 内存:2G 操作系统:Centos 7.3 x64 地域:华北 2(华北 2 可用区 A) 系统盘:40G 安装及配置 主要使用 nginx . php 和 ...
- 数据结构和算法总结(一):广度优先搜索BFS和深度优先搜索DFS
前言 这几天复习图论算法,觉得BFS和DFS挺重要的,而且应用比较多,故记录一下. 广度优先搜索 有一个有向图如图a 图a 广度优先搜索的策略是: 从起始点开始遍历其邻接的节点,由此向外不断扩散. 1 ...
- javascript中的隐式类型转化
javascript中的隐式类型转化 #隐式转换 ## "+" 字符串和数字 如果某个操作数是字符串或者能够通过以下步骤转换为字符串的话,+将进行拼接操作. 如果其中一个操作数是对 ...
- OVMF基础
什么是OVMF The Open Virtual Machine Firmware (OVMF) project aims to support firmware for Virtual Machin ...
- VMware Workstation 的安装和使用
https://blog.csdn.net/lamp_yang_3533/article/details/53136474 VMware Workstation 是一个虚拟PC的软件,利用VMwa ...
- 项目在tomcat里运行一段时间总是自动崩掉的问题排查与解决
最近的检验系统上线一段时间后,发现系统访问不了,tomcat总是会自动崩掉,一般遇到这种问题,程序员的第一反应都肯定是内存溢出. 确实是,但是java里内存分好几种,堆内存.栈内存.静态内存区等等,下 ...
- iOS开发中数据持久化
使用几个小例子分别实现 归档NSKeyedArchiver.NSUserDefaults.plist文件数据存储,简单直观.代码地址
- 集成学习之Boosting —— AdaBoost原理
集成学习大致可分为两大类:Bagging和Boosting.Bagging一般使用强学习器,其个体学习器之间不存在强依赖关系,容易并行.Boosting则使用弱分类器,其个体学习器之间存在强依赖关系, ...
- rest_framework之解析器、路由控制、分页
解析器 我们都知道,网络传输数据只能传输字符串格式的,如果是列表.字典等数据类型,需要转换之后才能使用 但是我们之前的rest_framework例子都没有转换就直接可以使用了,这是因为rest_fr ...