MySQL 下 ROW_NUMBER / DENSE_RANK / RANK 的实现
原文链接:http://hi.baidu.com/wangzhiqing999/item/7ca215d8ec9823ee785daa2b
MySQL 下 ROW_NUMBER / DENSE_RANK / RANK 的实现
CREATE TABLE test_rownum (
ID int,
Ke CHAR(1),
val INT
);
INSERT INTO test_rownum
SELECT 1, 'A', 1 UNION ALL
SELECT 2, 'A', 2 UNION ALL
SELECT 3, 'A', 3 UNION ALL
SELECT 4, 'B', 1 UNION ALL
SELECT 5, 'B', 2 UNION ALL
SELECT 6, 'B', 1 UNION ALL
SELECT 7, 'C', 3 UNION ALL
SELECT 8, 'C', 2 UNION ALL
SELECT 9, 'C', 2;
rownum 用于显示序号
ID 字段用于 标记 原有的序号位置.
普通的处理
等价于 ROW_NUMBER() OVER (ORDER BY ke, val)
SELECT
@rownum:=@rownum+1 AS rownum,
id,
ke,
val
FROM
(SELECT @rownum:=0) r,
test_rownum
ORDER BY
ke, val;
+--------+------+------+------+
| rownum | id | ke | val |
+--------+------+------+------+
| 1 | 1 | A | 1 |
| 2 | 2 | A | 2 |
| 3 | 3 | A | 3 |
| 4 | 4 | B | 1 |
| 5 | 6 | B | 1 |
| 6 | 5 | B | 2 |
| 7 | 8 | C | 2 |
| 8 | 9 | C | 2 |
| 9 | 7 | C | 3 |
+--------+------+------+------+
9 rows in set (0.00 sec)
PARTITION 的处理
等价于 ROW_NUMBER() OVER (PARTITION BY ke ORDER BY val)
SELECT
CASE
WHEN @ke != ke THEN @rownum:= 1
ELSE @rownum:= @rownum + 1
END AS rownum,
id,
@ke := ke AS ke,
val
FROM
(SELECT @ke:='') k,
(SELECT @rownum:=0) r,
test_rownum main
ORDER BY
ke, val;
+--------+------+------+------+
| rownum | id | ke | val |
+--------+------+------+------+
| 1 | 1 | A | 1 |
| 2 | 2 | A | 2 |
| 3 | 3 | A | 3 |
| 1 | 4 | B | 1 |
| 2 | 6 | B | 1 |
| 3 | 5 | B | 2 |
| 1 | 8 | C | 2 |
| 2 | 9 | C | 2 |
| 3 | 7 | C | 3 |
+--------+------+------+------+
9 rows in set (0.00 sec)
RANK DENSE_RANK 的处理
等价于 RANK() OVER (PARTITION BY ke ORDER BY val)
等价于 DENSE_RANK() OVER (PARTITION BY ke ORDER BY val)
SELECT
CASE
WHEN @ke != ke THEN @rownum:= 1
ELSE @rownum:= @rownum + 1
END AS ROW_NUMBER,
CASE
WHEN @ke != ke THEN @rank:= 1
WHEN @val = val THEN @rank
ELSE @rank:= @rownum
END AS RANK,
CASE
WHEN @ke != ke THEN @dense_rank:= 1
WHEN @val = val THEN @dense_rank
ELSE @dense_rank:= @dense_rank + 1
END AS DENSE_RANK,
id,
@ke := ke AS ke,
@val := val AS val
FROM
(SELECT @ke:='') k,
(SELECT @val:=0) v,
(SELECT @rownum:=0) r,
(SELECT @rank:=0) r2,
(SELECT @dense_rank:=0) d,
test_rownum main
ORDER BY
ke, val;
+------------+------+------------+------+------+------+
| ROW_NUMBER | RANK | DENSE_RANK | id | ke | val |
+------------+------+------------+------+------+------+
| 1 | 1 | 1 | 1 | A | 1 |
| 2 | 2 | 2 | 2 | A | 2 |
| 3 | 3 | 3 | 3 | A | 3 |
| 1 | 1 | 1 | 4 | B | 1 |
| 2 | 1 | 1 | 6 | B | 1 |
| 3 | 3 | 2 | 5 | B | 2 |
| 1 | 1 | 1 | 8 | C | 2 |
| 2 | 1 | 1 | 9 | C | 2 |
| 3 | 3 | 2 | 7 | C | 3 |
+------------+------+------------+------+------+------+
9 rows in set (0.00 sec)
=======================================================
两表关联情况下的测试.
CREATE TABLE test_rownum_main (
ID int,
Ke CHAR(1)
);
CREATE TABLE test_rownum_sub (
KeID int,
val INT
);
INSERT INTO test_rownum_main
SELECT 1, 'A' UNION ALL
SELECT 2, 'B' UNION ALL
SELECT 3, 'C';
INSERT INTO test_rownum_sub
SELECT 1, 1 UNION ALL
SELECT 1, 2 UNION ALL
SELECT 1, 3 UNION ALL
SELECT 2, 1 UNION ALL
SELECT 2, 2 UNION ALL
SELECT 2, 1 UNION ALL
SELECT 3, 3 UNION ALL
SELECT 3, 2 UNION ALL
SELECT 3, 2;
普通的处理
等价于 ROW_NUMBER() OVER (ORDER BY ke, val)
SELECT
@rownum:=@rownum+1 AS rownum,
main.id,
main.ke,
sub.val
FROM
test_rownum_main main
JOIN test_rownum_sub sub
ON (main.ID = sub.KeID),
(SELECT @rownum:=0) r
ORDER BY
ke, val;
+--------+------+------+------+
| rownum | id | ke | val |
+--------+------+------+------+
| 1 | 1 | A | 1 |
| 2 | 1 | A | 2 |
| 3 | 1 | A | 3 |
| 4 | 2 | B | 1 |
| 6 | 2 | B | 1 |
| 5 | 2 | B | 2 |
| 8 | 3 | C | 2 |
| 9 | 3 | C | 2 |
| 7 | 3 | C | 3 |
+--------+------+------+------+
9 rows in set (0.00 sec)
rownum 顺序不满足预期结果了。
可能是因为执行关联的时候, 就把 @rownum 计算了。
修改SQL语句.
SELECT
@rownum:=@rownum+1 AS rownum,
id,
ke,
val
FROM
(SELECT @rownum:=0) r,
(
SELECT
main.id,
main.ke,
sub.val
FROM
test_rownum_main main
JOIN test_rownum_sub sub
ON (main.ID = sub.KeID)
) subQuery
ORDER BY
ke, val;
+--------+------+------+------+
| rownum | id | ke | val |
+--------+------+------+------+
| 1 | 1 | A | 1 |
| 2 | 1 | A | 2 |
| 3 | 1 | A | 3 |
| 4 | 2 | B | 1 |
| 5 | 2 | B | 1 |
| 6 | 2 | B | 2 |
| 7 | 3 | C | 2 |
| 8 | 3 | C | 2 |
| 9 | 3 | C | 3 |
+--------+------+------+------+
9 rows in set (0.00 sec)
PARTITION 的处理
等价于 ROW_NUMBER() OVER (PARTITION BY ke ORDER BY val)
SELECT
CASE
WHEN @ke != ke THEN @rownum:= 1
ELSE @rownum:= @rownum + 1
END AS rownum,
id,
@ke := ke AS ke,
val
FROM
(SELECT @ke:='') k,
(SELECT @rownum:=0) r,
(
SELECT
main.id,
main.ke,
sub.val
FROM
test_rownum_main main
JOIN test_rownum_sub sub
ON (main.ID = sub.KeID)
) subQuery
ORDER BY
ke, val;
+--------+------+------+------+
| rownum | id | ke | val |
+--------+------+------+------+
| 1 | 1 | A | 1 |
| 2 | 1 | A | 2 |
| 3 | 1 | A | 3 |
| 1 | 2 | B | 1 |
| 2 | 2 | B | 1 |
| 3 | 2 | B | 2 |
| 1 | 3 | C | 2 |
| 2 | 3 | C | 2 |
| 3 | 3 | C | 3 |
+--------+------+------+------+
9 rows in set (0.00 sec)
DENSE_RANK 的处理
RANK 的处理
等价于 DENSE_RANK() OVER (PARTITION BY ke ORDER BY val)
等价于 RANK() OVER (PARTITION BY ke ORDER BY val)
SELECT
CASE
WHEN @ke != ke THEN @rownum:= 1
ELSE @rownum:= @rownum + 1
END AS ROW_NUMBER,
CASE
WHEN @ke != ke THEN @rank:= 1
WHEN @val = val THEN @rank
ELSE @rank:= @rownum
END AS RANK,
CASE
WHEN @ke != ke THEN @dense_rank:= 1
WHEN @val = val THEN @dense_rank
ELSE @dense_rank:= @dense_rank + 1
END AS DENSE_RANK,
id,
@ke := ke AS ke,
@val := val AS val
FROM
(SELECT @ke:='') k,
(SELECT @val:=0) v,
(SELECT @rownum:=0) r,
(SELECT @rank:=0) r2,
(SELECT @dense_rank:=0) d,
(
SELECT
main.id,
main.ke,
sub.val
FROM
test_rownum_main main
JOIN test_rownum_sub sub
ON (main.ID = sub.KeID)
) subQuery
ORDER BY
ke, val;
+------------+------+------------+------+------+------+
| ROW_NUMBER | RANK | DENSE_RANK | id | ke | val |
+------------+------+------------+------+------+------+
| 1 | 1 | 1 | 1 | A | 1 |
| 2 | 2 | 2 | 1 | A | 2 |
| 3 | 3 | 3 | 1 | A | 3 |
| 1 | 1 | 1 | 2 | B | 1 |
| 2 | 1 | 1 | 2 | B | 1 |
| 3 | 3 | 2 | 2 | B | 2 |
| 1 | 1 | 1 | 3 | C | 2 |
| 2 | 1 | 1 | 3 | C | 2 |
| 3 | 3 | 2 | 3 | C | 3 |
+------------+------+------------+------+------+------+
9 rows in set (0.00 sec)
MySQL 下 ROW_NUMBER / DENSE_RANK / RANK 的实现的更多相关文章
- SQL2005四个排名函数(row_number、rank、dense_rank和ntile)的比较
排名函数是SQL Server2005新加的功能.在SQL Server2005中有如下四个排名函数: .row_number .rank .dense_rank .ntile 下面分别介绍一下这四个 ...
- ROW_NUMBER、RANK、DENSE_RANK的用法
--NND,索性把2005的一起帖出来. ROW_NUMBER.RANK.DENSE_RANK的用法 (爱新觉罗.毓华 -- 广东深圳) SQL Server 引入几个新的排序(排名)函数,如ROW_ ...
- 四个排名函数(row_number、rank、dense_rank和ntile)的比较
排名函数是SQL Server2005新加的功能.在SQL Server2005中有如下四个排名函数: 1.row_number 2.rank 3.dense_rank 4.ntile 下面分别介绍一 ...
- SQL中的排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)简介
排名函数是Sql Server2005新增的功能,下面简单介绍一下他们各自的用法和区别. 在使用排名函数的时候需要注意以下三点: 1.排名函数必须有 OVER 子句. 2.排名函数必须有包含 ORDE ...
- Sql 四大排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)(转载)
Sql 四大排名函数(ROW_NUMBER.RANK.DENSE_RANK.NTILE)简介 排名函数是Sql Server2005新增的功能,下面简单介绍一下他们各自的用法和区别.我们新建一张O ...
- hive笔记之row_number、rank、dense_rank
hive中有三个与分组排序相关的分析函数(我起初也认为是窗口函数,后来看到手册里是把他们划到了Analytics functions下),row_number.rank.dense_rank,我一直傻 ...
- SQL With As 用法Sql 四大排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)简介
Sql 四大排名函数(ROW_NUMBER.RANK.DENSE_RANK.NTILE)简介 排名函数是Sql Server2005新增的功能,下面简单介绍一下他们各自的用法和区别.我们新建一张O ...
- sql server 2000 对应 sql server 2005的row_number()、rank()、DENSE_RANK( )、ntile( )等用法
转自CSDN:http://blog.csdn.net/htl258/article/details/4006717 SQL server 2005新增的几个函数,分别是row_number( ).r ...
- row_number()、rank()、dense_rank()、ntile()
原文:row_number().rank().dense_rank().ntile() SQL2005中row_number()等函数的用法 2005比2000新增了几个函数,分别是row_numbe ...
随机推荐
- [PWA] Customize the Splash Screen of a PWA built with create-react-app
Android displays a splash screen for PWAs based on the icons and names you provide, but iOS just dis ...
- EffectiveJava(20)使用子类型化优化标签类
标签类:其中有许多样板代码,包括枚举声明,标签域和条件语句 如果要给它添加风格,除了有权限修改源码之外,你还得给每个条件语句都添加一个条件,否则就会在运行时失败 标签类过于冗长,容易出错,并且效率低下 ...
- json-server模拟接口获取mock数据
转载:http://blog.csdn.net/stevennest/article/details/76167343 安装json-server 运行以下命令 cnpm install json-s ...
- Node.js 把图片流送到客户端
效果: 代码: var http=require('http'); var fs=require('fs'); var path=require('path'); var mime=require(' ...
- python的偏函数(partial)
偏函数就是固定原函数的某个参数,比如newadd就是固定了add方法的第一个参数,让a=3,这样对newadd方法只要传入参数B就可以实现add方法了,刚看偏函数的写法可能会不适应,因为partial ...
- TCP/IP详解 卷一(第十八章 TCP连接的建立和终止)
建立连接 建立一个TCP连接时会发生下述情况 1.客户TCP发送一个SYN(同步)分节,它告诉服务器将在(待建立)连接中发送的数据的初始序列号. 2.服务器确认(ACK)客户的SYN,同时自己也得发送 ...
- 【Excle数据透视表】如何利用图标集将销售数据划分为五个等级
我们如何用图标集来直观看出订单情况呢? 现在有数据如下: 步骤 选中"订单列"→开始→条件格式→图标集→等级→ 此时,在每个数字前面都出现了一个等级符号了 查看预置五等级图标集的规 ...
- WCF实现上传图片功能
初次学习实现WCF winform程序的通信,主要功能是实现图片的传输. 下面是实现步骤: 第一步: 首先建立一个类库项目TransferPicLib,导入wcf需要的引用System.Service ...
- asp.net core mvc视频A:笔记3-6.视图数据共享之session/cache
第一部分:Session讲解 会话级别的,怎么区分呢?以浏览器为单位,比如IE,搜狗等等,都算一个单独的会话 修改3.5项目 控制器代码 前端显示 startup.cs中配置并启用Session 运行 ...
- docker教程之从一头雾水到不一头雾水(3)
本文主要是介绍Docker容器的相关内容 容器创建 我们已经知道,镜像是只读的,而基于镜像创建出来的容器是可读写的,所以,一般我们实际中,会经常使用对应镜像创建容器并且使用这些容器.同样,如果我们想要 ...