MSSQL2005Ranking函數集

--> Title : MSSQL2005Ranking函數集

--> Author : wufeng4552

--> Date : 2009-11-03

一、row_number

row_number函数的用途是非常广泛,这个函数的功能是为查询出来的每一行记录生成一个序号。row_number函数的用法如下面的SQL语句所示

use Northwind

go

select row_number()over(order by TerritoryID)cnt,

TerritoryID,

RegionID

from Territories

/*

row_number TerritoryID RegionID

-------------------- -------------------- -----------

1 01581 1

2 01730 1

3 01833 1

4 02116 1

5 02139 1

6 02184 1

7 02903 1

8 03049 3

9 03801 3

*/

其中row_number列是由row_number函数生成的序号列。在使用row_number函数是要使用over子句选择对某一列进行排序,然后才能生成序号。

注意點:

row_number函数生成序号的基本原理是先使用over子句中的排序语句对记录进行排序,然后按着这个顺序生成序号。over子句中的order by子句与SQL语句中的order by子句没有任何关系,这两处的order by 可以完全不同,如下面的SQL语句所示

use Northwind

go

select row_number()over(order by (select 1))[row_number],

TerritoryID,

RegionID

from Territories order by newid()

/*

row_number TerritoryID RegionID

-------------------- -------------------- -----------

3 01833 1

52 98052 2

9 03801 3

41 80202 2

19 20852 1

27 40222 1

26 33607 4

50 95060 2

*/

如果不想按照某一字段排序可以這樣

use Northwind

go

select row_number()over(order by (select 1))[row_number],

TerritoryID,

RegionID

from Territories

--or

select row_number()over(order by getdate())[row_number],

TerritoryID,

RegionID

from Territories

如果先分組,然後再排序則可以用PARTITION BY 關鍵字

use Northwind

go

select row_number()over(partition by RegionID order by getdate() )[row_number],

TerritoryID,

RegionID

from Territories order by RegionID desc

/*

row_number TerritoryID RegionID

-------------------- -------------------- -----------

1 72716 4

2 75234 4

3 78759 4

4 29202 4

5 30346 4

6 31406 4

7 32859 4

8 33607 4

1 44122 3

2 45839 3

3 48075 3

4 48084 3

*/

我们可以使用row_number函数来实现查询表中指定范围的记录,一般将其应用到Web应用程序的分页功能上 :

use Northwind

go

;with wufeng4552

as

(select row_number()over(order by getdate() )[row_number],

TerritoryID,

RegionID

from Territories

)

select * from wufeng4552 where [row_number] between 2 and 7

/*

row_number TerritoryID RegionID

-------------------- -------------------- -----------

2 01730 1

3 01833 1

4 02116 1

5 02139 1

6 02184 1

7 02903 1

(7 個資料列受到影響)

*/

二、rank

rank函数考虑到了over子句中排序字段值相同的情况,为了更容易说明问题 創建測試表

use Northwind

go

if object_id('tempdb..#')is not null drop table #

go

select top 6 * into # from Territories

--插入幾筆重複值

insert # select '01581','Westboro',1 union all

select '01730','Bedford',1 union all

select '01833','Georgetow',1

select TerritoryID,

TerritoryDescription

from # order by TerritoryID

/*

TerritoryID TerritoryDescription

-------------------- --------------------------------------------------

01581 Westboro

01581 Westboro

01730 Bedford

01730 Bedford

01833 Georgetow

01833 Georgetow

02116 Boston

02139 Cambridge

02184 Braintree

*/

use Northwind

go

if object_id('tempdb..#')is not null drop table #

go

select top 6 * into # from Territories

--插入幾筆重複值

insert # select '01581','Westboro',1 union all

select '01730','Bedford',1 union all

select '01833','Georgetow',1

select rank()over(order by TerritoryID)[row_number],

TerritoryID

from #

/*

row_number TerritoryID

-------------------- --------------------

1 01581

1 01581

3 01730

3 01730

5 01833

5 01833

7 02116

8 02139

9 02184

*/

從上面的結果來看TerritoryID相同的 序號相同01730 序號從3 開始而不是2

rank函数的使用方法与row_number函数完全相同

--2000的實現方法

select

[row_number]=isnull((select count(*) from # where TerritoryID<t.TerritoryID),0)+1,

TerritoryID

from # t order by TerritoryID

/*

row_number TerritoryID

----------- --------------------

1 01581

1 01581

3 01730

3 01730

5 01833

5 01833

7 02116

8 02139

9 02184

(9 個資料列受到影響)

*/

如果先分組,然後再排序則可以用PARTITION BY 關鍵字

select rank()over(partition by RegionID order by TerritoryID)[row_number],

TerritoryID

from #

三、dense_rank

  dense_rank函数的功能与rank函数类似,只是在生成序号时是连续的,而rank函数生成的序号有可能不连续。如上面的例子中如果使用dense_rank函数

use Northwind

go

if object_id('tempdb..#')is not null drop table #

go

select top 6 * into # from Territories

--插入幾筆重複值

insert # select '01581','Westboro',1 union all

select '01730','Bedford',1 union all

select '01833','Georgetow',1

select dense_rank()over(order by TerritoryID)[row_number],

TerritoryID

from #

/*

row_number TerritoryID

-------------------- --------------------

1 01581

1 01581

2 01730

2 01730

3 01833

3 01833

4 02116

5 02139

6 02184

(9 個資料列受到影響)

*/

--2000的實現方法

select

[row_number]=isnull((select count(distinct TerritoryID) from # where TerritoryID<t.TerritoryID),0)+1,

TerritoryID

from # t order by TerritoryID

/*

row_number TerritoryID

----------- --------------------

1 01581

1 01581

2 01730

2 01730

3 01833

3 01833

4 02116

5 02139

6 02184

(9 個資料列受到影響)

*/

四、ntile

ntile函数可以对序号进行分组处理。这就相当于将查询出来的记录集放到指定长度的数组中,每一个数组元素存放一定数量的记录。ntile函数为每条记录生成的序号就是这条记录所有的数组元素的索引(从1开始)。也可以将每一个分配记录的数组元素称为ntile函数有一个参数,用来指定桶数。下面的SQL语句使用ntile函数对表进行了装桶处理:

use Northwind

go

if object_id('tempdb..#')is not null drop table #

go

select top 6 * into # from Territories

--插入幾筆重複值

insert # select '01581','Westboro',1 union all

select '01730','Bedford',1 union all

select '01833','Georgetow',1

select TerritoryID,

TerritoryDescription,

ntile(4)over(order by getdate())[Groups]

from #

select TerritoryID,

TerritoryDescription,

ntile(4)over(partition by RegionID order by getdate())[Groups]

from #

/*

TerritoryID TerritoryDescription Groups

<span styl

你可能感兴趣的:(sql,Go)