【译】高级T-SQL进阶系列 (七)【上篇】:使用排序函数对数据进行排序
【译注:此文为翻译,由于本人水平所限,疏漏在所难免,欢迎探讨指正】
原文链接:传送门。
什么是排序函数(Ranking Functions)?
排序函数基于一组记录的集合返回一个排序值。一个排序值其实就是一个数字,典型的它都是从1开始并且对于每一个新的排序值它都是按1递增的。根据排序函数的不同,对于数据集中的每一行来说,返回的排序值有可能是唯一的,或者一些数据行会具有一样的排序值。在接下来的章节中,我将浏览下这些不的排序函数,以及它们是如何使用的。
使用排序函数(Ranking Function)的例子
在一个分区中每行的排序数字都是从1开始递增的。在一个排序函数中,一个“分区”指的其实就是一组数据行,它们对于指定的分区列具有相同的值(因而把它们归为一个分区)。如果对于一个分区的两行它们的排序列(在ORDER BY 中指定的列)具有相同的值,那么它们两个都会得到相同的排序值。为了更好的理解如何 使用Rank函数,让我们看看它的句法:
RANK ( ) OVER ( [ PARTITION BY <partition_column> ] ORDER BY <order_by_column> )
其中:
- <partition_column>:定义了一个或者多个列名,它们将用来对数据进行分区;
- <order by column>:定义了一个或者多个列表,它们将用来对各个分区的输出进行排序;
注意:
PARTITION BY子句是可选的。如果没有使用 PARTITION BY子句,那么数据会基于一个分区进行排序。如果你在Rank函数中指定了PARTITION BY子句,那么对于数据集中的每个分区排序值都会被重置为1的。
既然现在你已经了解了Rank函数是做什么的,以及它的句法,那么我会运行几个Rank函数的例子。我所有的例子都会使用AdventureWorks2012数据库。如果你想跟着我的示例,那么你可以从下列位置下载 AdventureWorks2012数据库:http://msftdbprodsamples.codeplex.com/releases/view/93587。
对于我使用Rank函数的第一个例子,让我来运行下面的代码:
USE AdventureWorks2012;
GO
SELECT PostalCode, StateProvinceID,
RANK() OVER
(ORDER BY PostalCode ASC) AS RankingValue
FROM Person.Address
WHERE StateProvinceID IN (23,46);
列表1:简单的Rank函数的例子
当我运行列表1的代码,我得到了结果1的输出:
PostalCode StateProvinceID RankingValue
--------------- --------------- --------------------
03064 46 1
03064 46 1
03106 46 3
03276 46 4
03865 46 5
83301 23 6
83402 23 7
83501 23 8
83702 23 9
83864 23 10
结果1: 当运行列表1的代码产生的输出
如果你查看结果1的输出,你可以看到由Rank函数产生的值在RankingValue列中。在这个例子中,我是基于PostalCode列进行排序的。每一个唯一的PostalCode值都会得到一个不同的排序值。如果你查看输出的结果行,对于PostalCode 03064,你将会看到两行,其中每一行都有一个排序值1。因为有两个PostalCode为03064的数据行,排序值2便被跳过了。对于PostalCode 03106,其排序值便会为3。剩下的RankingValue值会按次序进行分配,因为它们的PostalCode值都是唯一的。
因为Rank函数的PARTITION BY子句没有被用在列表1中,整个数据集被认为是一个单独的分区。如果我想对于每一个唯一的StateProvinceID值来重新开始我的RankingValue值,那么我必须要做的所有的事情便是基于StateProvinceID对我的结果进行分区,在列表2中我以PostalCode进行排序并以StateProvinceID进行分区。
USE AdventureWorks2012;
GO
SELECT PostalCode, StateProvinceID,
RANK() OVER
(PARTITION BY StateProvinceID
ORDER BY PostalCode ASC) AS RankingValue
FROM Person.Address
WHERE StateProvinceID IN (23,46);
列表2:使用PARTITION BY子句
当我运行列表2的代码,我得到了结果2的输出。
PostalCode StateProvinceID RankingValue
--------------- --------------- --------------------
83301 23 1
83402 23 2
83501 23 3
83702 23 4
83864 23 5
03064 46 1
03064 46 1
03106 46 3
03276 46 4
03865 46 5
结果2:当运行列表2的输出
在列表2的输出有两个分区。一个分区包含了所有的StateProvinceID值为23的PostalCode值,第二个分区包含了StateProvinceID为46的PostalCode值。注意对每一个分区来说RankingValue都是从1开始的。
使用稠密排序(DENSE RANK)函数的例子
当我对每个重复的PostalCode值运行Rank函数,我的输出便会跳过一个RankingValue值。
通过使用DENSE RANK函数,我会生成一个不会跳过任何值的排序值。DENSE RANK函数具有如下的句法:
DENSE_RANK ( ) OVER ( [ PARTIION BY <partition_column> ] ORDER BY <order_by_column> )
其中:
- <partition_column>:定义了一个或者多个列名,其用来对数据进行分区。
- <order_by_column>: 定义了一个或者多个列名,其用来对各个分区的输出进行排序。
在句法上RANK 函数和 DENSE RANK函数唯一的不同其实就是函数名的不同而已。
为了浏览DENSE RANK函数让我来运行列表3的代码:
USE AdventureWorks2012;
GO
SELECT PostalCode, StateProvinceID,
DENSE_RANK() OVER
(PARTITION BY StateProvinceID
ORDER BY PostalCode ASC) AS RankingValue
FROM Person.Address
WHERE StateProvinceID IN (23,46);
列表3:使用DENSE_RANK
当我运行列表3的代码,我得到了结果3的输出:
PostalCode StateProvinceID RankingValue
--------------- --------------- --------------------
83301 23 1
83402 23 2
83501 23 3
83702 23 4
83864 23 5
03064 46 1
03064 46 1
03106 46 2
03276 46 3
03865 46 4
结果3:运行列表3产生的输出
通过查看结果3的输出你会看到PostalCode为03064的数据行具有相同的RankingValue值。但是下一个PostalCode具有一个排序值2而不是3。记住在结果2中RANK函数对于这个相同的重复PostalCode其跳过了一个RankingValue值。使用DENSE_RANK函数,当遇到一个重复的PostalCode值时,它不会跳过一个RankingValue值。相反的,甚至当遇到重复的排序行值时,它会保证所有的RankingValue值都是连续的。
(To be continued...)
【译】高级T-SQL进阶系列 (七)【上篇】:使用排序函数对数据进行排序的更多相关文章
- 【译】高级T-SQL进阶系列 (七)【下篇】:使用排序函数对数据进行排序
此文为翻译,由于本人水平有限,疏漏在所难免,欢迎探讨指正. 原文链接:传送门. 使用NTILE函数的示例 NTILE函数将一组记录分割为几个组.其返回的分组数是由一个整形表达式指定的.如下你会找到NT ...
- Bing Maps进阶系列七:Bing Maps功能导航菜单华丽的变身
Bing Maps进阶系列七:Bing Maps功能导航菜单华丽的变身 Bing Maps Silverlight Control所提供的功能导航是非常强大的,在设计上对扩展的支持非常好,提供了许多用 ...
- 深入理解javascript函数进阶系列第一篇——高阶函数
前面的话 前面的函数系列中介绍了函数的基础用法.从本文开始,将介绍javascript函数进阶系列,本文将详细介绍高阶函数 定义 高阶函数(higher-order function)指操作函数的函数 ...
- 【SQL必知必会笔记(2)】检索数据、排序检索数据
上个笔记中介绍了一些关于数据库.SQL的基础知识,并且创建我们后续练习所需的数据库.表以及表之间的关系,从本文开始进入我们的正题:SQL语句的练习. 文章目录 1.检索数据(SELECT语句) 1.1 ...
- SQL进阶系列之7用SQL进行集合运算
写在前面 集合论是SQL语言的根基,因为这种特性,SQL也被称为面向集合语言 导入篇:集合运算的几个注意事项 注意事项1:SQL能操作具有重复行的集合(multiset.bag),可以通过可选项ALL ...
- Linq To Sql进阶系列(六)用object的动态查询与保存log篇
动态的生成sql语句,根据不同的条件构造不同的where字句,是拼接sql 字符串的好处.而Linq的推出,是为了弥补编程中的 Data != Object 的问题.我们又该如何实现用object的动 ...
- SQL进阶系列之12SQL编程方法
写在前面 KISS -- keep it sweet and simple 表的设计 注意命名的意义 英文字母 + 阿拉伯数字 + 下划线"_" 属性和列 编程的方针 写注释 注意 ...
- SQL进阶系列之10HAVING子句又回来了
写在前面 HAVING子句的处理对象是集合而不是记录 各队,全队点名 --各队,全体点名! CREATE TABLE Teams (member CHAR(12) NOT NULL PRIMARY K ...
- SQL进阶系列之11让SQL飞起来
写在前面 SQL的性能优化是数据库使用者必须面对的重要问题,本节侧重SQL写法上的优化,SQL的性能同时还受到具体数据库的功能特点影响,这些不在本节讨论范围之内 使用高效的查询 参数是子查询时,使用E ...
随机推荐
- 一看就会一做就废系列:说说 RECOVER UNTIL CANCEL
这里是:一看就会,一做就废系列 数据库演示版本为 19.3 (12.2.0.3) 该系列涉及恢复过程中使用的 5 个语句: 1. recover database 2. recover databas ...
- 【新特性速递】F.doPostBack的说明文档
FineUIPro/Mvc/Core的下个版本(v6.1.0),我们对客户端JS函数 F.doPostBack 进行了增强,并增加说明文档. 如果你还没有查阅过FineUI的客户端文档,可以收藏下这个 ...
- Spring事务之传播机制
Spring事务传播机制:Spring在TransactionDefinition接口中规定了种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套时事务如何进行传播.即协调已经有事务标识的方法之 ...
- javaSE--基础02
本章目标 一. 运算符★赋值运算符关系运算符逻辑运算符 三元运算符 二. 进制与位运算符[选学] 三. 流程控制结构 √ 四. 顺序结构 √ 五. 分支结构★ 六. 循环结构★ 七. ...
- Linux - Shell - find - 进阶: 时间与大小
概述 继续 find 这次的内容, 参数稍微要 复杂那么一丢丢 背景 刚学会了 基础 的参数 现在来了解一些 时间 和 空间 的参数 一说到操控时间空间, 感觉立马起来了... 准备 OS cento ...
- 【C语言】多维数组
C 语言支持多维数组.多维数组声明的一般形式如下: type name[size1][size2]...[sizeN]; 二维数组 多维数组最简单的形式是二维数组.一个二维数组,在本质上,是一个一维数 ...
- 励志成为优产的母猪--------猜数游戏 ,历史记录,pickle保存,队列deque
# pickle 可以处理复杂的序列化语法.(例如自定义的类的方法,游戏的存档等),存档以文件的形式保存 参见 https://www.cnblogs.com/abobo/p/8080447.html ...
- my codestyle
代码风格 缩进 缩进采用4个空格或tab. 原则是:如果地位相等,则不需要缩进:如果属于某一个代码的内部代码就需要缩进. 变量命名 变量命名遵守遵从驼峰命名法,统一使用lowerCamelCase风格 ...
- sublime 最常用的快捷键.gif
Ctrl+D 把光标放在文本上,按下⌘+ D将选择这个文本.多次按下⌘+ D则会增加匹配项 Alt+F3 会选中光标所在文本的所有匹配项 Ctrl+Shift+' 这是一个法宝,也许你希望所有的属性保 ...
- 利用ansible-playbook一键部署ELK(ElasticSearch,logstash and kibana)
一.部署前环境介绍: es集群5台(es01,es02,es03,es04,es05),logstash服务器1台(logstash2),kibana服务器1台(kibana2),模拟apache服务 ...