想了解更多关于 NTILE()

Posted

技术标签:

【中文标题】想了解更多关于 NTILE()【英文标题】:Want to learn more on NTILE() 【发布时间】:2013-01-16 09:43:10 【问题描述】:

我正在阅读 ms sql 的 RANKING 函数。我了解除 NTILE() 之外的其他功能。 假设我有这些数据:

   StudentID     MARKS  
      S1           75  
      S2           83
      S3           91
      S4           83
      S5           93  

那么,如果我执行NTILE(2) OVER(ORDER BY MARKS desc),结果会是什么?为什么? 如果它是NTILE(3) 怎么办? 简单的解释任何人?

【问题讨论】:

如果你在一个大集合上做 NTILE,你可以使用上 ntile 的最小值(或下 ntile 的最大值)作为 Median 的代理。这可能比在很多行上运行中位数更便宜。 不,你不能。如果您每次运行时都希望查询得到正确答案,则不会。 【参考方案1】:

把它想象成桶,NTILE(2) 会产生 2 个桶,一半的行的值为 1,另一半的值为 2

例子

create table  #temp(StudentID char(2),    Marks  int) 
insert #temp  values('S1',75 ) 
insert #temp  values('S2',83)
insert #temp  values('S3',91)
insert #temp  values('S4',83)
insert #temp  values('S5',93 ) 


select NTILE(2) over(order by Marks),*
from #temp
order by Marks

这是输出,因为你的行数是奇数,所以桶 1 会多出 1 行

1   S1  75
1   S2  83
1   S4  83
2   S3  91
2   S5  93

如果你再添加一行

insert #temp  values('S6',92 ) 

现在两个桶都有 3 行

1   S1  75
1   S2  83
1   S4  83
2   S3  91
2   S6  92
2   S5  93

实际上我从未在生产代码中使用过 NTILE,但我可以看到你需要将结果分成 n 个桶的用途

【讨论】:

【参考方案2】:

它将数据按照标记的降序排列,然后分成2组。

如果不能将数据分成相等的组,那么前几组的行数将多于后几组。

所以 NTILE(2) 会给你

StudentID       MARKS       NTILE  
      S5           93           1 
      S3           91           1 
      S2           83           1
      S4           83           2
      S1           75           2 

类似地,NTILE(3) 会给你

StudentID       MARKS       NTILE  
      S5           93           1 
      S3           91           1 
      S2           83           2
      S4           83           2
      S1           75           3  

【讨论】:

【参考方案3】:

我经常使用 NTILE 将电子邮件列表拆分为存储桶以进行 10/10/80 测试。例如,我们正在测试一封电子邮件的主题行,并希望将两个选项中的一个发送给列表中的每个 10%,将效果更好的一个发送给剩余的 80%。

SELECT [字段列表],(NTILE(10) OVER(order by newid()))-1 AS Segment FROM [data]

“order by newid()”确保随机顺序。 “[NTILE ...]-1”语法是我们使用其他一些工具进行文本解析而不是整数数学的直接结果,因此从 0-9 而不是 1-10 运行结果更容易.细分字段将填充 0-9 之间的值,我可以使用它很容易地分离出 10% 的记录,并且不止一次用于对它们进行多次努力的活动。

如果您需要具有可复制结果的查询,则需要在“order by”子句中使用确定性的内容,或者添加带有 GUID 的列以用于 order by 子句。

PARTITION BY 子句将用于根据状态、职业或其他一些预先确定的分组创建存储桶组,即 NTILE(10) OVER (PARTITION BY State ORDER BY newid()) 等。我相信 ORDER BY 子句是必需的 - PARTITION BY 是可选的。

【讨论】:

【参考方案4】:

在 Ntile 函数中,它首先计算行数并除以 ntile 中传递的参数,然后根据商组成一组相等的行并对它们进行排名,然后剩余的行将由每个组从顶部开始分配一种移动方式,不会从最少的行中取出它,例如,如果 group1 有 4 行,那么它将在其组中占据第 5 行而不是最后一行。

谢谢

【讨论】:

【参考方案5】:

Ntile 不使用分区子句,只需根据 ntile(number) 中的数字划分数据集,这样:如果行数为 7,例如:1,1,1,2,3,4,5 ntile( 3) 将给出 3,2,2。我是如何得到 3、2、2 的?首先假设 7 为 6(减一以使其相等), 6/3 给出 2,2,2 ,然后添加 +!到第一个分区。如果行数是偶数,那么没有问题。只需划分数据集

Ntile 使用分区子句,只需根据数据集中的值划分数据集,这样:如果行数为 7,示例行值为:1,1,1,2,3,4,5 则:ntile( 3)按值分区将给出:1,2,3,1,1,1,1。我是怎么得到这个的?首先根据值分解数据集:这里,1,1,1 是一个分区,接下来所有值形成一个不同的分区。然后开始为每个分区分配 ntile rank。这里1,1,1会变成1,2,3然后继续下一个分区,你只能拉到ntile()函数中指定的数字为止

【讨论】:

以上是关于想了解更多关于 NTILE()的主要内容,如果未能解决你的问题,请参考以下文章

关于 varchar 数据类型的困惑

在哪里可以了解有关 C++0x 的更多信息? [关闭]

jmeter随笔(29)-关于自己的jar包和beanshell的使用

关于“敏捷开发”和“DevOps ”转型,你需要知道什么?

如何使用列值范围应用 NTILE(4)?

社区视频 | 挖矿是什么?