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 DML等级3:在SQL Server中实现关系模型
我使用密集等级函数为学生生成随机排名。请给我代码,只提取前5%的学生