DENSE_RANK 根据特定顺序
DENSE_RANK according to particular order
您好,我有 table 的数据,我想根据排序的日期顺序从第一组名称开始输出 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
您将如何更正查询?如果有多个有效答案,将选择 simplest/shortest 一个作为答案。谢谢。
已添加:
感谢@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
先按日期排列不同的名称,然后加入 table:
;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
您可以使用:
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
值的情况。
您好,我有 table 的数据,我想根据排序的日期顺序从第一组名称开始输出 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
您将如何更正查询?如果有多个有效答案,将选择 simplest/shortest 一个作为答案。谢谢。
已添加:
感谢@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
先按日期排列不同的名称,然后加入 table:
;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
您可以使用:
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
值的情况。