T-SQL“dense_rank”,每个等级的最大行数

Posted

技术标签:

【中文标题】T-SQL“dense_rank”,每个等级的最大行数【英文标题】:T-SQL "dense_rank" with a maximum number of rows with each rank 【发布时间】:2014-01-06 13:18:53 【问题描述】:

如果我这样做

dense_rank() over (order by colname),

对于列 colname 中具有相同值的所有行,我得到相同的排名。

但是,我想将具有相同排名的行数限制为 @maxrows,以便当 @maxrows 行在 colname 中具有相同值时,即使 colname 的值仍然是,也会为下一行分配一个新排名一样的。

我怎样才能做到这一点?

【问题讨论】:

您可以使用 Ntile 函数,因为 NTILE 函数允许您通过为每一行分配一个图块编号,将结果中的行与图块(大小相等的行组)相关联。您指定要跟踪的图块数量作为函数的输入,并在 OVER 子句中指定逻辑顺序。 NTILE 几乎与 OP 要求的相反 - 您指定需要多少组,而不是组的大小。此外,NTILE 会将具有不同 colname 值的行放在同一组中,这与DENSE_RANK() 完全不同。 【参考方案1】:

您可以通过使用多个排名函数来实现这一点。我们在中间和另一列使用ROW_NUMBER() 来执行平局:

declare @maxRows int
set @maxRows = 5

; With InitialRanks as (
    select DENSE_RANK() OVER (ORDER BY type) as rnk,* from sys.objects
), OrderedRanks as (
    select (ROW_NUMBER() OVER (PARTITION BY rnk ORDER by object_id)-1)
            / @maxRows as rn,*
    from InitialRanks
)
select DENSE_RANK() OVER (ORDER BY rnk,rn),* from OrderedRanks

在这里,每个(最终)排名值最多只能得到 5 列。排名基于type,但我们使用object_id 作为辅助列来计算允许特定排名的行的顺序。


原来我把上面的事情弄得太复杂了——不需要第一个 CTE 和第一个 DENSE_RANK,因为它实际上是 ROW_NUMBER() 函数中 type 列的代理——所以为什么不只需直接使用type 列并简化事情:

declare @maxRows int
set @maxRows = 5

; With  OrderedRanks as (
    select (ROW_NUMBER() OVER (PARTITION BY type ORDER by object_id)-1)
            / @maxRows as rn,*
    from sys.objects
)
select DENSE_RANK() OVER (ORDER BY type,rn),* from OrderedRanks

【讨论】:

非常有创意地使用排名函数! 感谢这个非常聪明的解决方案!

以上是关于T-SQL“dense_rank”,每个等级的最大行数的主要内容,如果未能解决你的问题,请参考以下文章

阶梯T-SQL:超越基础等级9:动态T-SQL代码

外文转译:通过楼梯到T-SQL DML等级3:在SQL Server中实现关系模型

T-SQL 查询获取子元素的最大值

我使用密集等级函数为学生生成随机排名。请给我代码,只提取前5%的学生

使用 hive 中的 rank/dense_rank 查找每个部门的第二高薪水

SQL Server / T-SQL:查询优化帮助