SQL中几个常用的排序函数

排序函数是做什么的?

排序函数的作用是基于一个结果集返回一个排序值。排序值就是一个数字,这个数字是典型的以1开始且自增长为1的行值。由ranking函数决定排序值可以使唯一的对于当前结果集,或者某些行数据有相同的排序值。在接下来我将研究不同的排序函数以及如何使用这些函数。

使用RANK函数的例子

RANK函数每个分区的排序都是从1开始。“partition”是一组有相同指定分区列值的数据行的集合。如果一个分区中有相同排序列的值(这个列指定在ORDER BY后面),然后相同排序列值的行将会分配给相同的排序值。有点绕口,为了更好的理解,如何使用,让我们看下下面的语法:

RANK ( ) OVER ( [ PARTITION BY <partition_column> ] ORDER BY <order_by_column> )

这里有几个参数:

  • <partition_column>: 指定一个或者多个列名作为分区数据
  • <order by column>: 确定一个或者多个列然后用来对每个分区的输出数据进行排序
注意:

PARTITION BY子句是一个可选项。如是不使用,数据将按照一个分区对所有数据进行排序。如果指定了PARTITION BY子句,则每个分区的数据集都各自进行从1开始的排序。

现在对RANK函数的语法和如何工作有了一定的理解,下面运行一对该函数的例子。需要说明一下我的例子的运行环境都是AdventureWorks2012 数据库,可以从网络上下载这里给出一个下载地址http://msftdbprodsamples.codeplex.com/releases/view/93587。

下面是第一个使用RANK函数的例子:


1

2

3

4

5

6

7


USE AdventureWorks2012;

GO

SELECT PostalCode, StateProvinceID,

RANK() OVER

(ORDER BY PostalCode ASC) AS RankingValue

FROM Person.Address

WHERE StateProvinceID IN (23,46);

Code1: 只有RANK函数不分区

运行代码后,结果集如下:

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
 

如上所示,按照RANK函数使结果集按照列RankingValue进行了排序。在例子中排序是基于列PostalCode。每一个唯一的PostalCode 得到一个不同的排序值。这里PostalCode 为03054 有两行数据,它们的排序值都是1,因为有两个1,所以排序2就被跳过。其余的排序继续往下依次进行。

由于RANK函数的分区子句没有使用,那么整个结果集被当做一个单一的分区。如果我打算按照独立的StateProvinceID 进行分区,然后进行排序我可以做按照如下的例子来执行:


1

2

3

4

5

6

7

8


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);

Code 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

在输出结果中分为了两个分区,一个分区是StateProvinceID 是23的,而另一个是包含StateProvinceID 值为46的、注意每个分区都是从1开始进行排序的。

使用DENSE_RANK函数

当运行RANK函数时,由于有一个相同的PostalCode ,输出结果会跳过一个排序值2,通过使用DENSE_RANK函数我能生成一个不省略改相同排序值的一个排序。该函数语法如下:

DENSE_RANK ( ) OVER ( [ PARTIION BY <partition_column> ] ORDER BY <order_by_column> )

语法中唯一的不同就是函数名称的改变。让我们运行下面的代码来研究下函数:


1

2

3

4

5

6

7

8


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);

Code3: 使用 DENSE_RANK

结果集如下:

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

根据结果集,可以看到PostalCode 03064 有相同的排序值,但是下一个PostalCode 的排序值为2而不是3了。与RANK函数的不同就是当有重复排序值时它能保证了排序序列中没有省略排序。

使用NTILE 函数

该函数将数据集合划分为不同的组。得到组的数量是根据指定的一个整数来确定的。下面就是NTILE 函数的语法:

NTILE (integer_expression) OVER ( [ PARTIION BY <partition_column> ] ORDER BY <order_by_column> )

Where:

  • <integer_expression>: 确定创建不同组的数量
  • <partition_column>:确定一个或者多个列用来进行分区数据
  • <order by column>: 确定一个或者多个列然后用来对每个分区的输出数据进行排序

为了更好地理解,让我们回顾几个不同的例子。运行下面代码:


1

2

3

4

5

6

7


USE AdventureWorks2012;

GO

SELECT PostalCode, StateProvinceID,

NTILE(2) OVER

(ORDER BY PostalCode ASC) AS NTileValue

FROM Person.Address

WHERE StateProvinceID IN (23,46);

Code4: 使用NTILE 函数查询

运行结果如下:

PostalCode      StateProvinceID NTileValue
--------------- --------------- --------------------
03064           46              1
03064           46              1
03106           46              1
03276           46              1
03865           46              1
83301           23              2
83402           23              2
83501           23              2
83702           23              2
83864           23              2

通过观察结果集,能很容易发现有两个不同的NTileValue 的列值,1和2。两个不同的NTileValue 值被创建是因为这里我查询语句中指定了“NTILE(2)” 。这个括号内的值就是整数表达式,作用就是指定创建的组的数量。当看到结果集中有10行数据,前五行NTileValue 为1,后五行为2。不出所料整个结果集被平均分成了两组。

如果不能被平均分配到不同个组的时候,比如参数导致有不能被整除的时候。当发生这种情况是那么将不能被整除的行按序放到每一个组内,知道所有的剩余行都被分配完毕。如下所示:


1

2

3

4

5

6

7

8


USE AdventureWorks2012;

GO

DECLARE @Integer_Expression int = 4;

SELECT PostalCode, StateProvinceID,

NTILE(@Integer_Expression) OVER

(ORDER BY PostalCode ASC) AS NTileValue

FROM Person.Address

WHERE StateProvinceID IN (46,23);

Code 5: NTile 查询不能平均分配结果集

运行代码如下:

PostalCode      StateProvinceID NTileValue
--------------- --------------- --------------------
03064           46              1
03064           46              1
03106           46              1
03276           46              2
03865           46              2
83301           23              2
83402           23              3
83501           23              3
83702           23              4
83864           23              4

这里直奔主题,10个结果行,参数为4需要分成4组,那么10除以4 余数为2。这意味着前两组会多一行比后两组。如上所示,在这个输出结果中1和2组都有3行,然后NTileValue 为3和4的组只有两行。

跟RANK函数一样,我们也能使用partition 分区子句来创建分区下的NTILE 函数。当引入PARTITION BY 子句时,每个分区内部都从1开始进行NTILE排序。下面展示一下运行代码:


1

2

3

4

5

6

7

8

9


USE AdventureWorks2012;

GO

DECLARE @Integer_Expression int = 3;

SELECT PostalCode, StateProvinceID,

NTILE(@Integer_Expression) OVER

(PARTITION BY StateProvinceID

ORDER BY PostalCode ASC) AS NTileValue

FROM Person.Address

WHERE StateProvinceID IN (46,23);

Code 6: 使用分区子句后,使用NTile 查询不平均分组

运行代码如下:

PostalCode      StateProvinceID NTileValue
--------------- --------------- --------------------
83301           23              1
83402           23              1
83501           23              2
83702           23              2
83864           23              3
03064           46              1
03064           46              1
03106           46              2
03276           46              2
03865           46              3

通过结果集可以看到加入分区子句后对NTILE函数的影响。如果观察输出的NTileValue列值,可以发现排序从StateProvinceID  为46开始重新从1开始。这就是加入“PARTITION BY StateProvinceID”子句的作用,先分区在分组排序。

使用 ROW_NUMBER 函数

当打算为输出的行生成一个行号时,行号顺序地自增长,步长为1.为了完成目标我们需要使用ROW_NUMBER 函数。

下面是使用ROW_NUMBER 的例子:

ROW_NUMBER () OVER ( [ PARTIION BY <partition_expressions> ] ORDER BY <order_by_column> )

代码如下:


1

2

3

4

5

6

7


USE AdventureWorks2012;

GO

SELECT PostalCode, StateProvinceID,

ROW_NUMBER() OVER

(ORDER BY PostalCode ASC) AS RowNumber

FROM Person.Address

WHERE StateProvinceID IN (46,23);

Code  7: 使用ROW_NUMBER 函数

运行结果如下:

PostalCode      StateProvinceID RowNumber
--------------- --------------- --------------------
03064           46              1
03064           46              2
03106           46              3
03276           46              4
03865           46              5
83301           23              6
83402           23              7
83501           23              8
83702           23              9
83864           23              10

如果想对输出的PostalCode进行排序,但是你打算先按照StateProvinceID进行分组,再排序。为了实现上述要求,我加入PARTITION BY子句,代码如下:


1

2

3

4

5

6

7

8


USE AdventureWorks2012;

GO

SELECT PostalCode, StateProvinceID,

ROW_NUMBER() OVER

(PARTITION BY StateProvinceID

ORDER BY PostalCode ASC) AS RowNumber

FROM Person.Address

WHERE StateProvinceID IN (46,23);

Code 8: 使用PARTITION BY 子句和ROW_NUMBER 函数查询

运行结果如下:

PostalCode      StateProvinceID RowNumber
--------------- --------------- --------------------
83301           23              1
83402           23              2
83501           23              3
83702           23              4
83864           23              5
03064           46              1
03064           46              2
03106           46              3
03276           46              4

正如你看到的结果,通过添加分区子句,行数列RowNumber 每个不同的StateProvinceID 值都会从1重新开始排序。

时间: 2024-09-30 23:52:24

SQL中几个常用的排序函数的相关文章

处理PHP中字符串的常用操作及函数

[合肥开源IT教育][php培训][开源IT教育][合肥php培训][合肥软件开发] 1. 确定一个字符串的长度 这是最为常见和基础的例子,对于确定一个字符串的长度,我们应该使用strlen()函数,比如要获取下面字符串$text 的长度:$text = "sunny day"; $count = strlen($text); // $count = 9 2. 截取文本来创建一个概要 新闻性质的网站通常会在发布正文中的开头部分截取大约200字左右,并在末尾加上省略号来形成一个摘要.你可

SQL Server之排序函数

Sql Server2005数据库自带一个排序函数ROW_NUMBER(),列表为: 语法:row_number() : over(子句)1.使用row_number()函数进行编号: select row_number() over(order by Sage) id ,* from Student 原理:先按Sage进行排序,排序完后,给每条数据进行编号.注:在使用over等开窗函数时,over里头的分组及排序的执行晚于"where,group by,order by"的执行.结果

STL中的各种排序函数

标准c++库中提供六种排序方法:qsort(),  sort(),stable_sort(),  partial_sort(),  list::sort(),  set/multiset qsort()比sort()慢并且不能排序构造函数.虚函数,一般不推荐使用.写一个比较函数传递给qsort()很麻烦: 后五个排序中,前三个是泛型算法,后两个则使用了某些容器的特别特性.所有的这些都是使用operator()来比较对象,但是在必要时指定用户自己的比较函数. 后五个每个都提供了自己的特征: 1.s

SQL中的join操作总结(非常好)

1.1.1 摘要 Join是关系型数据库系统的重要操作之一,SQL Server中包含的常用Join:内联接.外联接和交叉联接等.如果我们想在两个或以上的表获取其中从一个表中的行与另一个表中的行匹配的数据,这时我们应该考虑使用Join,因为Join具体联接表或函数进行查询的特性 本文将通过具体例子介绍SQL中的各种常用Join的特性和使用场合: 目录 Inner join Outer join Cross join Cross apply Cross apply 和 Inner join的区别

C++ 排序函数 sort(),qsort()的使用方法

想起来自己天天排序排序,冒泡啊,二分查找啊,结果在STL中就自带了排序函数sort,qsort,总算把自己解脱了~ 所以自己总结了一下,首先看sort函数见下表: 函数名 功能描写叙述 sort 对给定区间全部元素进行排序 stable_sort 对给定区间全部元素进行稳定排序 partial_sort 对给定区间全部元素部分排序 partial_sort_copy 对给定区间复制并排序 nth_element 找出给定区间的某个位置相应的元素 is_sorted 推断一个区间是否已经排好序 p

在SQL中使用CLR提供基本函数对二进制数据进行解析与构造

? 二进制数据包的解析一般是借助C#等语言,在通讯程序中解析后形成字段,再统一单笔或者批量(表类型参数)提交至数据库,在通讯程序中,存在BINARY到struct再到table的转换. 现借助CLR提供基本的INT2HEX(小端)等函数,在SQL中直接解析数据包. ? 基本函数 [Microsoft.SqlServer.Server.SqlFunction(Name = "Time2UTCBin")] public static SqlBinary Time2UTCBin(DateTi

SQL Server中截取字符串常用函数

SQL Server 中截取字符串常用的函数: 1.LEFT ( character_expression , integer_expression ) 函数说明:LEFT ( '源字符串' , '要截取最左边的字符数' ) 返回从字符串左边开始指定个数的字符 select LEFT('SQL_Server_2008',4 ); 返回结果:SQL_ 2.RIGHT ( character_expression , integer_expression ) 函数说明:RIGHT ( '源字符串'

SQL点滴30—SQL中常用的函数

原文:SQL点滴30-SQL中常用的函数 该文章转载自http://www.cnblogs.com/jiajiayuan/archive/2011/06/16/2082488.html 别人的总结,很详细. 以下所有例子均Studnet表为例:  计算字符串长度len()用来计算字符串的长度 select sname ,len(sname) from student 字符串转换为大.小写lower() 用来将一个字符串转换为小写,upper() 用来将一个字符串转换为大写 select lowe

SQL 中的常用函数及使用

在SQL中我们使用的函数有很多,我们经常使用的就是下面的一些函数,那么我一一列举数来: 1:聚合函数:MAX 返回指定数据的最大值. MIN 返回指定数据的最小值. COUNT 返回指定组中项目的数量. AVG 返回指定组中的平均值,空值被忽略. SUM 返回指定数据的和,只能用于数字列,空值被忽略. 2:数学函数:ceiling 取上限floor 取下限 qound 四舍五入abs 取绝对值pi 圆周率 SQRT - 开根号SQUARE - 平方根 3:字符串函数:UPPER 将字符串中的小写