众所周知,NTILE函数是SQL Server 2005的新特性之一,用于将有序分区中的行分发到指定数目的组中。各个组有编号,编号从一开始。那么在没有出现SQL Server 2005之前我们又是怎样做来达到这样的效果的呢?

众所周知,NTILE函数是SQL Server 2005的新特性之一,用于将有序分区中的行分发到指定数目的组中。各个组有编号,编号从一开始。对于每一个行,NTILE 将返回此行所属的组的编号。如果分区的行数不能被整数整除,则将导致一个成员有两种大小不同的组。按照 OVER 子句指定的顺序,较大的组排在较小的组前面。用NTILE函数计算排名值与其它方法一样简单(分区排名方案和排名值效率分析【图文+测试代码】 ),唯一的区别在于,NTILE函数接受一个表示组的数量的参数,而其它的方法是没有参数的。

SQL代码和效果如下:      

Code
if OBJECT_ID ('Sales') is not null
    drop table Sales;
create table Sales
(
    empid varchar(10) not null primary key,
    qty int not null
)
insert into Sales (empid ,qty ) values ('A',300);
insert into Sales (empid ,qty ) values ('B',100);
insert into Sales (empid ,qty ) values ('C',200);
insert into Sales (empid ,qty ) values ('D',200);
insert into Sales (empid ,qty ) values ('E',250);
insert into Sales (empid ,qty ) values ('F',300);
insert into Sales (empid ,qty ) values ('H',250);
insert into Sales (empid ,qty ) values ('I',250);
insert into Sales (empid ,qty ) values ('J',100);
insert into Sales (empid ,qty ) values ('K',200);
insert into Sales (empid ,qty ) values ('G',100);




--------------------------------------------------
select empid,qty,NTILE (9) over (order by qty) as tile from Sales 

效果图:

      

ntopenprocess函数有什么用 ntile函数_Sales

ntopenprocess函数有什么用 ntile函数_SQL_02


      那么在没有出现SQL Server 2005之前我们又是怎样做来达到这样的效果的呢?下面我将给大家介绍两种方法来达到这个需求:

方法一:首先计算表的行号(排名值),根据指定的组的数量得到每组内的记录数量。然后利用组号计算公式:(行号-1)/组大小+1,返回每条记录的组号。

SQL代码如下:      


Code
eclare @numtiles int;
set @numtiles =9;--组数

select empid,qty,CAST ((rn-1)/tilesize +1 as int ) as tile
    from (select empid,qty,rn,1.0*numrows/@numtiles as tilesize from (select empid,qty,(select COUNT (*) from Sales as S2 where S2 .qty <S1.qty or S2 .qty =S1.qty and S2 .empid <=S1.empid) as rn,(select COUNT (*) from Sales ) as numrows from Sales as S1 ) as D1) as D2 order by qty,empid ;

方法二:首先计算表的行号(排名值),根据指定的组的数量得到每组内的记录数量。然后利用下面组号计算公式,返回每条记录的组号。

If(行号<=(组大小+1)* 剩余行数) then

      组号=(行号-1)/(组大小+1)+1

Else

      组号=(行号-剩余行数-1)/组大小+1

SQL代码如下:      

Code
declare @numtile int;
set @numtile =9;--组数

select empid ,qty,rn,
    case when rn<=(tilesize+1)*remainder
            then (rn-1)/(tilesize+1)+1
         else (rn-remainder-1)/(tilesize)+1
    end as tiles
    from 
    (
        select empid,qty,rn,numrows/@numtile as tilesize,numrows%@numtile as remainder 
            from 
            (
                select empid,qty,(select COUNT (*) from Sales as S2 where S2.qty <S1.qty or S2.qty =S1.qty and S2.empid <=S1.empid) as rn ,(select COUNT (*) from Sales ) as numrows from Sales as S1 
            ) as D1
    ) as D2 order by qty,empid