DENSE_RANK 根据特定顺序

Posted

技术标签:

【中文标题】DENSE_RANK 根据特定顺序【英文标题】:DENSE_RANK according to particular order 【发布时间】:2015-12-23 06:31:46 【问题描述】:

您好,我有一个数据表,我想根据排序的日期顺序从第一组名称开始输出名称的dense_rank。例如

DROP TABLE MyTable
SELECT * INTO MyTable FROM (
  VALUES ('2015-12-23', 'ccc'),('2015-12-21', 'aaa'),
         ('2015-12-20', 'bbb'),('2015-12-22', 'aaa')
) t (date, name)
SELECT DENSE_RANK() OVER (ORDER BY name) rank, * FROM MyTable ORDER BY date

对于上面的查询,我得到了

rank    date    name
2   2015-12-20  bbb
1   2015-12-21  aaa
1   2015-12-22  aaa
3   2015-12-23  ccc

您可以看到日期已排序(好),等级分配给组中的名称(好),但等级不是从第一组名称开始,例如我想要

rank    date    name
1   2015-12-20  bbb
2   2015-12-21  aaa
2   2015-12-22  aaa
3   2015-12-23  ccc

您将如何更正查询?如果有多个工作答案,将选择最简单/最短的一个作为答案。谢谢。

补充:

感谢@lad2025 和@GiorgosBetsos 澄清我的问题。排序直接根据日期和日期在我的情况下是独一无二的。名称可以重复和不连续出现。所以使用('2015-12-24', 'aaa'),输出是

rank    date    name
1   2015-12-20  bbb
2   2015-12-21  aaa
2   2015-12-22  aaa
3   2015-12-23  ccc
4   2015-12-24  aaa

【问题讨论】:

你已经发布了两个相同的输出 ('2015-12-24', 'aaa') 应该去哪里? (2015-12-22 之后排名第 2)还是排名第 4? ('2015-12-21', 'eee')('2015-12-22', 'eee') 这样的额外行呢? 【参考方案1】:

你可以使用:

SELECT DENSE_RANK() OVER (ORDER BY minGrpDate),
       [date], name
FROM (
  SELECT MIN([date]) OVER (PARTITION BY grp) AS minGrpDate,
         [date], name
  FROM (       
    SELECT [date], name,
           ROW_NUMBER() OVER (ORDER BY [date])
           -
           ROW_NUMBER() OVER (PARTITION BY name ORDER BY [date]) AS grp
    FROM mytable) AS t ) AS s
ORDER BY Date

说明:

grp 字段标识具有相同name 的连续记录岛。 minGrpDate,使用grp计算,是每个岛屿的最小日期。 现在我们可以使用minGrpDate 应用DENSE_RANK() 来获得所需的排名。

注意1:上述查询处理name字段中的不连续性,即具有相同名称的非连续字段的情况。

注意2:查询不处理不同name值共享相同date值的情况。

Demo here

【讨论】:

如果您的实际数据在name 字段中不包含任何不连续性,那么此解决方案会不必要地复杂。 @Giorgi 的答案在这种情况下会更合适 感谢@GiorgosBetsos,这正是我所需要的。尽管我无法理解您的两个 row_number() 相互减去,但我仍然认为您的回答很出色。【参考方案2】:

先按日期排序不同的名字,然后加入表格:

;WITH cte AS(SELECT name, ROW_NUMBER() OVER(ORDER BY MIN(date)) rn 
             FROM dbo.MyTable 
             GROUP BY name)
SELECT c.rn, m.date, m.name
FROM cte c
JOIN dbo.MyTable m ON m.name = c.name
ORDER BY m.date

【讨论】:

如果有像('2015-12-24', 'aaa')这样的额外行怎么办? @GiorgosBetsos,排名为 2。 OP 没有提到他在这种情况下想要什么。 所以,在这种情况下,日期将是无序的。 @user1589188,你能评论一下Giorgos的评论吗? 谢谢@GiorgiNakeuri。有趣的是,您在没有使用 dense_rank 的情况下回答了问题。不知道是不是我的问题不符合dense_rank的目的?

以上是关于DENSE_RANK 根据特定顺序的主要内容,如果未能解决你的问题,请参考以下文章

[HIVE] rank() dense_rank() row_number()的学习

DENSE_RANK() OVER (Order by UniqueIdentifer) 问题

使用 DENSE_RANK 拆分数据集

【SQL】根据一个字段分组求另一个字段的最大值,并带出其他字段

如何使用快速编码根据特定的排序顺序对自定义对象进行排序

如何根据特定顺序对休眠结果进行排序