我一直在为自己总结 - SQL服务器中的窗口函数。
但这对我来说也很重要 - 不仅要知道如何来编写函数,而且还应该在我应该使用的场景中使用它们。
我可以诚实地说,我对Rank
函数没有答案,在DENSE_RANK
函数中我应该使用5
非常明确:
示例:有2
个竞争对手,1
他们同时完成了结束 - 所以两者都获得相同的排名(使用DENSE_RANK) - 两者都会得到3
。其他2
竞争对手(同时也完成)将获得排名Rank
(等等......)
问题:
在什么情况下我应该使用DECLARE @t TABLE(NAME NVARCHAR(MAX),val money)
insert INTO @t SELECT 'a',100
insert INTO @t SELECT 'a',100
insert INTO @t SELECT 'a',100
insert INTO @t SELECT 'a',100
insert INTO @t SELECT 'b',200
insert INTO @t SELECT 'b',200
insert INTO @t SELECT 'd',400
insert INTO @t SELECT 'e',500
insert INTO @t SELECT 'f',600
select Name,
val,
ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY name),
val/ SUM(val) OVER(PARTITION BY NAME ) AS '1AgainstTotalHimself',
val/ SUM(val) OVER( ) AS '1AgainstOthers' ,
NTILE(2) OVER ( PARTITION BY NAME ORDER BY name) AS 'ntile2' ,
NTILE(2) OVER ( ORDER BY name) AS 'ntile' , -- ( 9%2=1 , so group #1 will get more number)
RANK( ) OVER ( ORDER BY name ) AS Rank,
DENSE_RANK( ) OVER (ORDER BY name) AS DENSERANK
from @t
函数,我知道如何生成数字,但我没有看到使用它的任何场景
可视化示例:
{{1}}
答案 0 :(得分:3)
RANK()
可以看作是TOP (n) WITH TIES
的等价物,除了后者只能在整个集合中获取指定的行,而前者也可以在分区上执行此操作。
因此,如果您需要选择每组前五个结果,但包括与每个组中的#5行绑定的所有行(如果有),RANK()
将为您解决此问题:
WITH ranked AS (
SELECT
EmployeeID,
FirstName,
LastName,
DepartmentID,
Salary,
rnk = RANK() OVER (PARTITION BY DepartmentID ORDER BY Salary DESC)
FROM
dbo.Employee
)
SELECT
EmployeeID,
FirstName,
LastName,
DepartmentID,
Salary
FROM
ranked
WHERE
rnk <= 5
;
答案 1 :(得分:2)
在与Aaron Bertrand交谈之后 - 我终于得到了“人为措辞描述”何时使用Rank:
dense_rank()
当4人并列首位时,下一个最好的人就是 第二。rank()
是4个人并列第一,下一个最好的人 第五。没有任何技术原因你会使用它 另一方面,这就是你想要显示和消费数字的方式。在 有些运动,例如,他们想要一个干净的第1,第2,第3。的在 其他人,他们希望你的排名反映(!!!)有多少人提前完成(!!!) 你好(好吧,减1,取决于你的观点)。
所以对于Rank,我不关心在1,2,3世界中的第一名或第二名“ - 它更具竞争性:数字本身也代表了第二名的重量。(例如)
所以,如果100人在05:00获胜而我在05:01之后获胜 - 那么他们将在DenseRank中获得第一名(我将排在第二位)。但是排名 - 他们都是1,我将是101.所以它增加了“第二重量”。
此外,现在我看到密集这个词的来源。它正在消除“重量”
另一种解释:
用dense_rank:看2,并不代表我几乎是最好的。可能有100人在05:00完成
排名:看2,意味着我几乎是最好的。