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

select NTILE(4) OVER(order by [SubTime] desc) as ntile,* from [Order]

  查询结果如下图所示:

  

  Order表的总记录数是6条,而上面的Sql语句ntile函数指定的组数是4,那么Sql Server2005是怎么来决定每一组应该分多少条记录呢?这里我们就需要了解ntile函数的分组依据(约定)。

  ntile函数的分组依据(约定):

  1、每组的记录数不能大于它上一组的记录数,即编号小的桶放的记录数不能小于编号大的桶。也就是说,第1组中的记录数只能大于等于第2组及以后各组中的记录数。

  2、所有组中的记录数要么都相同,要么从某一个记录较少的组(命名为X)开始后面所有组的记录数都与该组(X组)的记录数相同。也就是说,如果有个组,前三组的记录数都是9,而第四组的记录数是8,那么第五组和第六组的记录数也必须是8。

  这里对约定2进行详细说明一下,以便于更好的理解。

  首先系统会去检查能不能对所有满足条件的记录进行平均分组,若能则直接平均分配就完成分组了;若不能,则会先分出一个组,这个组分多少条记录呢?就是 (总记录数/总组数)+1 条,之所以分配 (总记录数/总组数)+1 条是因为当不能进行平均分组时,总记录数%总组数肯定是有余的,又因为分组约定1,所以先分出去的组需要+1条。

  分完之后系统会继续去比较余下的记录数和未分配的组数能不能进行平均分配,若能,则平均分配余下的记录;若不能,则再分出去一组,这个组的记录数也是(总记录数/总组数)+1条。

  然后系统继续去比较余下的记录数和未分配的组数能不能进行平均分配,若能,则平均分配余下的记录;若还是不能,则再分配出去一组,继续比较余下的......这样一直进行下去,直至分组完成。

  举个例子,将51条记录分配成5组,51%5==1不能平均分配,则先分出去一组(51/5)+1=11条记录,然后比较余下的 51-11=40 条记录能否平均分配给未分配的4组,能平均分配,则剩下的4组,每组各40/4=10 条记录,分配完成,分配结果为:11,10,10,10,10,晓菜鸟我开始就错误的以为他会分配成 11,11,11,11,7。

  根据上面的两个约定,可以得出如下的算法:

//mod表示取余,div表示取整.
if(记录总数 mod 桶数==0)
{
  recordCount=记录总数 div 桶数;
  //将每桶的记录数都设为recordCount.
}
else
{
  recordCount1=记录总数 div 桶数+1;
  int n=1;//n表示桶中记录数为recordCount1的最大桶数.
  m=recordCount1*n;
  while(((记录总数-m) mod (桶数- n)) !=0)
  {
    n++;
    m=recordCount1*n;
  }
  recordCount2=(记录总数-m) div (桶数-n);
  //将前n个桶的记录数设为recordCount1.
  //将n+1个至后面所有桶的记录数设为recordCount2.
}
int recordTotal = 51;//记录总数.
int tcount = 5;//总组数.
string groupResult = "将" + recordTotal + "条记录分成" + tcount + "组,";
int recordCount = 0;//平均分配时每组的记录数.
//不能平均分配
int recordCount1 = 0;//前n个组每组的记录数.
int recordCount2 = 0;//第n+1组至后面所有组每个组的记录数.
int n = 1;//组中记录数为recordCount1的最大组数(前n组).
if (recordTotal % tcount == 0)//能平分.
{
recordCount = recordTotal / tcount;//每组的记录数.
}
else//不能平分.
{
recordCount1 = recordTotal / tcount + 1;//不能平分则先分出一组-前n组每组的记录数.
int m = recordCount1 * n;//已分配的记录数.
while ((recordTotal - m) % (tcount - n) != 0)//余下的记录数和未分配的组不能进行平分.
{
//还是不能平分,继续分出一组.
n++;
m = recordCount1 * n;
}
recordCount2 = (recordTotal - m) / (tcount - n);//余下的记录数和未分配的组能进行平分或者只剩下最后一组了-第n+1组至后面所有组每个组的记录数.
}
//输出.
if (recordCount != 0)
{
groupResult += "能平均分配,每组" + recordCount + "个.";
}
else
{
groupResult += "不能平均分配,前" + n + "组,每组" + recordCount1 + "个,";
if (n < tcount - 1)
{
//groupResult += "第" + (groupNumber + 1) + "组至后面所有组,每组" + recordCount2 + "个.";
groupResult += "第" + (n + 1) + "组至第" + tcount + "组,每组" + recordCount2 + "个.";
}
else
{
groupResult += "第" + (n + 1) + "组" + recordCount2 + "个.";
}
}
ViewData["result"] = groupResult;

  

  根据上面的算法,如果总记录数为59,总组数为5,则 n=4 , recordCount1=12 , recordCount2=11,分组结果为 :12,12,12,12,11。

  如果总记录数为53,总组数为5,则 n=3 , recordCount1=11 , recordCount2=10,分组结果为:11,11,11,10,10。

  就拿上面的例子来说,总记录数为6,总组数为4,通过算法得到 n=2 , recordCount1=2 , recordCount2=1,分组结果为:2,2,1,1。

select ntile,COUNT([ID]) recordCount from
(
select NTILE(4) OVER(order by [SubTime] desc) as ntile,* from [Order]
) as t
group by t.ntile

  运行Sql,分组结果如图:

  

  比对算法与Sql Server的分组结果是一致的,说明算法没错。:)

ntile函数的更多相关文章

  1. SQLServer中利用NTILE函数对数据进行分组的一点使用

    本文出处:http://www.cnblogs.com/wy123/p/6908377.html NTILE函数可以按照指定的排序规则,对数据按照指定的组数(M个对象,按照某种排序分N个组)进行分组, ...

  2. 分组函数NTILE函数

    这个分组函数 并不是 group by的分组.

  3. 关于sql row_number,rank,dense_rank,ntile函数

    row_number排序最好用它,它依次排名,不出现相同名次,如:1,2,3,4,5 rank出现相同排名,且跳过相同的排名号排下一名,如:1,1,3,4,5, dense_rank出现相同排名,不跳 ...

  4. sqlserver 中row_number,rank,dense_rank,ntile排名函数的用法

    1.row_number() 就是行号 2.rank:类似于row_number,不同之处在于,它会对order by 的字段进行处理,如果这个字段值相同,那么,行号保持不变 3.dense_rank ...

  5. SQL2005四个排名函数(row_number、rank、dense_rank和ntile)的比较

    排名函数是SQL Server2005新加的功能.在SQL Server2005中有如下四个排名函数: .row_number .rank .dense_rank .ntile 下面分别介绍一下这四个 ...

  6. SQL Server:排名函数row_number,rank,dense_rank,ntile详解

    1.Row_Number函数 row_number函数大家比较熟悉一些,因为它的用途非常的广泛,我们经常在分页与排序中用到它,它的功能就是在每一行中生成一个连续的不重复的序号 例如: select S ...

  7. 四个排名函数(row_number、rank、dense_rank和ntile)的比较

    排名函数是SQL Server2005新加的功能.在SQL Server2005中有如下四个排名函数: 1.row_number 2.rank 3.dense_rank 4.ntile 下面分别介绍一 ...

  8. Sql 四大排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)简介

    排名函数是Sql Server2005新增的功能,下面简单介绍一下他们各自的用法和区别.我们新建一张Order表并添加一些初始数据方便我们查看效果. CREATE TABLE [dbo].[Order ...

  9. SQL中的排名函数(ROW_NUMBER、RANK、DENSE_RANK、NTILE)简介

    排名函数是Sql Server2005新增的功能,下面简单介绍一下他们各自的用法和区别. 在使用排名函数的时候需要注意以下三点: 1.排名函数必须有 OVER 子句. 2.排名函数必须有包含 ORDE ...

随机推荐

  1. c#+.net常用功能点

    1.比较差集合,排除不在集合中的,即data是data1排除data2剩下的数据 var data1 = new List<string>(); var data2 = new List& ...

  2. 简单搭建一个SpringBoot

    1.SpringBoot下载 https://start.spring.io/ 选择工程类型,编译语言,版本,工程名称,需要支持组件等:选择好了以后点击生成项目. 之后会下载一个压缩文件,解压之后导入 ...

  3. unfortunately,*********** has stopped及卸载模拟器上的多余不用apk

    虽然不知道是怎么了,但是项目进不去了,害的我一脸雾水,百度了下好像没什么人遇到过这问题,都没找到解决办法,那只好来个简单粗暴的,卸载重新安装apk ,希望有大神知道原因和其他方法的欢迎留言或者评价给出 ...

  4. 浏览器登录EBS系统遇到问题总结

    1.可以登录EBS系统,但是职责位置为空白 这是兼容性视图问题,将ERP域名加入兼容性视图列表即可. 加入即可: 2.可以登录EBS系统,但是职责位置显示 “undefined” 这也是兼容性视图问题 ...

  5. 基于bootstrap的datepicker

    <script src="<%=path %>/js/bootstrap-datepicker.min.js"/> <script src=" ...

  6. Exp1 PC平台逆向破解 20165110 石钰

    Exp1 PC平台逆向破解 20165110 石钰 一.实践目标 1.实验背景 实践对象是pwn1的Linux可执行文件,该程序的正常该程序正常执行流程是:main调用foo函数(oo函数会简单回显任 ...

  7. String、StringBuilder、StringBuffer 区别

    public static void testStringBuffer(){ long start System currentTimeMillis(); StringBuffer sbuf = ne ...

  8. 52-python 画图二维

    Python--matplotlib绘图可视化知识点整理 1.折线图: import numpy as np import matplotlib.pyplot as plt from pylab im ...

  9. Python:a,*args,**kwargs的理解

    1.何时用这些参数? 在任何时候继承类和重写方法时,应当用到’*args’和’**kwargs’将接收到的位置参数和键值参数给父类方法 . 2.一句话清晰说明: a是常规的变量类型,比如int,str ...

  10. linux上安装MongoDB副本集(带keyfile安全认证以及用户权限)

    搭建前准备 MongoDB版本:4.0 主要参考搭建MongoDB副本集网站:https://www.jianshu.com/p/f021f1f3c60b 安装之前最好先确定一下几点: 防火墙关闭 M ...