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

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

01581                Westboro                                           1

01730                Bedford                                            1

01833                Georgetow                                          1

01581                Westboro                                           2

01730                Bedford                                            2

01833                Georgetow                                          3

02116                Boston                                             3

02139                Cambridge                                          4

02184                Braintree                                          4

*/

 

你可能感兴趣的:(MSSQL2005Ranking函數集)