博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[MSSQL]ROW_NUMBER函数
阅读量:6270 次
发布时间:2019-06-22

本文共 4600 字,大约阅读时间需要 15 分钟。

ROW_NUMBER()在SQL2K5版本中新增,该函数返回结果集分区内行的序列号,每个分区的第一行从 1 开始,连续不间断,后跟OVER BY子句或者PARTITION BY子句

先构造一张表,放一些数据进行,SQL脚本如下

--DROP TABLE T
CREATE TABLE T(GRP_A VARCHAR(20),GRP_B VARCHAR(20),GRP_C VARCHAR(20),VAL INT)
INSERT INTO T(GRP_A,GRP_B,GRP_C,VAL)
SELECT 'a1','b1','c1',10 union all
SELECT 'a1','b1','c2',20 union all
SELECT 'a1','b2','c2',30 union all
SELECT 'a1','b2','c3',40 union all
SELECT 'a1','b2','c3',50 union all
 
SELECT 'a2','b3','c3',12 union all
SELECT 'a2','b3','c3',22 union all
SELECT 'a2','b3','c3',32
 
SELECT * FROM T

执行查询后的结果:

GRP_A                GRP_B                GRP_C                VAL
-------------------- -------------------- -------------------- -----------
a1                   b1                   c1                   10
a1                   b1                   c2                   20
a1                   b2                   c2                   30
a1                   b2                   c3                   40
a1                   b2                   c3                   50
a2                   b3                   c3                   12
a2                   b3                   c3                   22
a2                   b3                   c3                   32
 
(8 行受影响)

ORDER BY子句

如果单独使用ORDER BY子句,则整个结果集为一个分区,

下边的SQL语句单使用了ORDER BY子句,先按GRP_A排序,然后根据排序后的结果额外生成一连续自增的NUM列

SELECT
*,
ROW_NUMBER()OVER(ORDER BY GRP_A) AS NUM
FROM T

结果集如下,不算复杂啊:

GRP_A                GRP_B                GRP_C                VAL         NUM
-------------------- -------------------- -------------------- ----------- --------------------
a1                   b1                   c1                   10          1
a1                   b1                   c2                   20          2
a1                   b2                   c2                   30          3
a1                   b2                   c3                   40          4
a1                   b2                   c3                   50          5
a2                   b3                   c3                   12          6
a2                   b3                   c3                   22          7
a2                   b3                   c3                   32          8
 
(8 行受影响)

跟不加ROW_NUMBER函数的区别就是增加了最后那一列,NUM,其值是递增的,增量为1

同理可以按照其它字段排序,如VAL,或者GRP_B,GRP_C等,列名不变,列值不变,变的是其它列的顺序

这个查询仅有一个分区,就是整个结果集,整个结果集内有这么一列,自增NUM列,可以用来分页或者啥的啥的

没有什么特别之处,ORDER BY 跟普通的ORDER BY 类似,也可以有多个列的排序,如:

SELECT
*,
ROW_NUMBER()OVER(ORDER BY GRP_A ASC,GRP_B DESC,VAL ASC) AS NUM
FROM T

最终影响的还是结果集中除NUM列外的其它数据的排序

 

PARTITION BY XXX ORDER BY YYY子句

使用PARTITION BY子句后,结果集就会按照该字段进行分区,这时候仍然要使用ORDER BY子句,影响的是分区内的排序,然后在每个分区内生成从1开始的自增列:

SELECT
*,
ROW_NUMBER()OVER(PARTITION BY GRP_A ORDER BY VAL) AS NUM
FROM T

这时候结果集发生变化了,必须得发生!

GRP_A                GRP_B                GRP_C                VAL         NUM
-------------------- -------------------- -------------------- ----------- --------------------
a1                   b1                   c1                   10          1
a1                   b1                   c2                   20          2
a1                   b2                   c2                   30          3
a1                   b2                   c3                   40          4
a1                   b2                   c3                   50          5
a2                   b3                   c3                   12          1
a2                   b3                   c3                   22          2
a2                   b3                   c3                   32          3
 
(8 行受影响)
结果集先是按照GRP_A字段进行了分区:a1分区和a2分区,分别为前五行和后三行,在每个分区内NUM从1递增,增量为1,排序规则为VAL ASC
嗯,很简单吧,
应用场景
比如我们有一张表,该表存储了某件商品的图片,商品与图片是一对多的关系,即一件商品有N件图片,现在要求取图片最多的那个商品
或者每件商品只取按照添加顺序的倒序取前两张图片,这时候就可以用ROW_NUMBER()OVER(PARTITION BY 商品编号 ORDER BY 添加时间 DESC) AS NUM来取
随后在结果集内过滤NUM于2的数据即可!
整体不算复杂,更多的应用场景还是分页时,当我们的自增主键不连续时,要取前20条数据,就可以利用该函数特性生成连续递增的NUM列,再BETWEEN即可
分页示例
SELECT * FROM (SELECT
*,
ROW_NUMBER()OVER(ORDER BY VAL) AS NUM
FROM T) AS SOMETABLENAME
WHERE NUM BETWEEN 1 AND 5

相对应的结果集

GRP_A                GRP_B                GRP_C                VAL         NUM
-------------------- -------------------- -------------------- ----------- --------------------
a1                   b1                   c1                   10          1
a2                   b3                   c3                   12          2
a1                   b1                   c2                   20          3
a2                   b3                   c3                   22          4
a1                   b2                   c2                   30          5
 
(5 行受影响)
仅返回了前五行
 

猜测您可能对下边的文章感兴趣

如果您喜欢该博客请点击右下角推荐按钮,您的推荐是作者创作的动力!

转载地址:http://uvlpa.baihongyu.com/

你可能感兴趣的文章
开发者论坛一周精粹(第五十四期) 求购备案服务号1枚!
查看>>
validate表单验证及自定义方法
查看>>
知识点002-yum的配置文件
查看>>
学习 Git(使用手册)
查看>>
javascript 中出现missing ) after argument list的错误
查看>>
RSA 加密解密
查看>>
Cause: org.apache.ibatis.ognl.ExpressionSyntaxException: Malformed OGNL expression:......
查看>>
路由模式 - direct
查看>>
form表单的target属性
查看>>
mysql的常用引擎
查看>>
Linux基础(day40)
查看>>
第二个Java应用和Tomcat的管理功能
查看>>
10.28 rsync工具介绍 10.29/10.30 rsync常用选项 10.31 rsync通过ssh同步
查看>>
使用Layer弹窗时遇到Layer.Close()后dom元素延迟性销毁的问题 @Gyb
查看>>
LVS DR +keepalived配置
查看>>
安装redis.msi 及启动命令
查看>>
k8s集群部署四(部署Flannel网络)
查看>>
C4C和Outlook的集成
查看>>
人脸检测,人脸识别,机器学习库Dlib在VS2015上的详细安装教程,示例运行
查看>>
数组——冒泡排序算法
查看>>