密集排名,按 A 列划分,按 B 列的变化递增,但按 C 列排序
Dense rank, partitioned by column A, incremented by change in column B but ordered by column C
我有一个table像这样
name|subtitle|date
ABC|excel|2018-07-07
ABC|excel|2018-08-08
ABC|ppt|2018-09-09
ABC|ppt|2018-10-10
ABC|excel|2018-11-11
ABC|ppt|2018-12-12
DEF|ppt|2018-12-31
我想添加一个在字幕发生变化时递增的列,如下所示:
name|subtitle|date|Group_Number
ABC|excel|2018-07-07|1
ABC|excel|2018-08-08|1
ABC|ppt|2018-09-09|2
ABC|ppt|2018-10-10|2
ABC|excel|2018-11-11|3
ABC|ppt|2018-12-12|4
DEF|ppt|2018-12-31|1
问题是,如果我执行 Dense_rank() over(按名称按字幕顺序分区),那么不仅会将所有字幕分组到一个组中,而且还会删除日期顺序。我也尝试过使用滞后函数,但当您尝试递增列时,它似乎不是很有用。
有没有简单的方法可以做到这一点?
请记住,我使用的 table 有数百个不同的名称。
快答
declare @table table (name varchar(20),subtitle varchar(20),[date] date )
insert into @table (name,subtitle,date)
values
('ABC','excel','2018-07-07'),
('ABC','excel','2018-08-08'),
('ABC','ppt','2018-09-09'),
('ABC','ppt','2018-10-10'),
('ABC','excel','2018-11-11'),
('ABC','ppt','2018-12-12'),
('DEF','ppt','2018-12-31');
with nums as (
select *,
case when subtitle != lag(subtitle,1) over (partition by name order by date)
then 1
else 0 end as num
from @table
)
select *,
1+sum(num) over (partition by name order by date) AS Group_Number
from nums
说明
你问的不完全是排名。您正在尝试 detect "islands" 在严格按日期排序的序列中名称和副标题相同。
为此,您可以将当前行的值与上一行的值进行比较。如果它们匹配,则您在同一个 "island" 中。如果没有,有一个开关。每次检测到更改时,您都可以使用它来发出例如 1
。
就是这样:
CASE WHEN subtitle != LAG(subtitle,1) OVER (PARTITION BY name ORDER BY date)
THEN 1
一旦你有了它,你就可以计算总计 运行 的变化数量:
sum(num) over (partition by name order by date) AS Group_Number
这将生成从 0 开始的值。要获取从 1 开始的数字,只需添加 1:
1+sum(num) over (partition by name order by date) AS Group_Number
更新
正如 T. Clausen 在评论中解释的那样,反转比较将摆脱 +1
:
with nums as (
select *,
case when subtitle = lag(subtitle,1) over (partition by name order by date)
then 0
else 1 end as num
from @table
)
select *,
sum(num) over (partition by name order by date) AS Group_Number
from nums
这也是一种更好的检测孤岛的方法,即使本例中的结果相同。第一个查询会产生这个结果:
name subtitle date num Group_Number
ABC excel 2018-07-07 0 1
ABC excel 2018-08-08 0 1
ABC ppt 2018-09-09 1 2
ABC ppt 2018-10-10 0 2
ABC excel 2018-11-11 1 3
ABC ppt 2018-12-12 1 4
DEF ppt 2018-12-31 0 1
当在边界处检测到字幕中断 除外时,查询发出 1
。
第二个查询returns:
name subtitle date num Group_Number
ABC excel 2018-07-07 1 1
ABC excel 2018-08-08 0 1
ABC ppt 2018-09-09 1 2
ABC ppt 2018-10-10 0 2
ABC excel 2018-11-11 1 3
ABC ppt 2018-12-12 1 4
DEF ppt 2018-12-31 1 1
在这种情况下,每次更改都会发出 1
,包括边界
我有一个table像这样
name|subtitle|date
ABC|excel|2018-07-07
ABC|excel|2018-08-08
ABC|ppt|2018-09-09
ABC|ppt|2018-10-10
ABC|excel|2018-11-11
ABC|ppt|2018-12-12
DEF|ppt|2018-12-31
我想添加一个在字幕发生变化时递增的列,如下所示:
name|subtitle|date|Group_Number
ABC|excel|2018-07-07|1
ABC|excel|2018-08-08|1
ABC|ppt|2018-09-09|2
ABC|ppt|2018-10-10|2
ABC|excel|2018-11-11|3
ABC|ppt|2018-12-12|4
DEF|ppt|2018-12-31|1
问题是,如果我执行 Dense_rank() over(按名称按字幕顺序分区),那么不仅会将所有字幕分组到一个组中,而且还会删除日期顺序。我也尝试过使用滞后函数,但当您尝试递增列时,它似乎不是很有用。
有没有简单的方法可以做到这一点?
请记住,我使用的 table 有数百个不同的名称。
快答
declare @table table (name varchar(20),subtitle varchar(20),[date] date )
insert into @table (name,subtitle,date)
values
('ABC','excel','2018-07-07'),
('ABC','excel','2018-08-08'),
('ABC','ppt','2018-09-09'),
('ABC','ppt','2018-10-10'),
('ABC','excel','2018-11-11'),
('ABC','ppt','2018-12-12'),
('DEF','ppt','2018-12-31');
with nums as (
select *,
case when subtitle != lag(subtitle,1) over (partition by name order by date)
then 1
else 0 end as num
from @table
)
select *,
1+sum(num) over (partition by name order by date) AS Group_Number
from nums
说明
你问的不完全是排名。您正在尝试 detect "islands" 在严格按日期排序的序列中名称和副标题相同。
为此,您可以将当前行的值与上一行的值进行比较。如果它们匹配,则您在同一个 "island" 中。如果没有,有一个开关。每次检测到更改时,您都可以使用它来发出例如 1
。
就是这样:
CASE WHEN subtitle != LAG(subtitle,1) OVER (PARTITION BY name ORDER BY date)
THEN 1
一旦你有了它,你就可以计算总计 运行 的变化数量:
sum(num) over (partition by name order by date) AS Group_Number
这将生成从 0 开始的值。要获取从 1 开始的数字,只需添加 1:
1+sum(num) over (partition by name order by date) AS Group_Number
更新
正如 T. Clausen 在评论中解释的那样,反转比较将摆脱 +1
:
with nums as (
select *,
case when subtitle = lag(subtitle,1) over (partition by name order by date)
then 0
else 1 end as num
from @table
)
select *,
sum(num) over (partition by name order by date) AS Group_Number
from nums
这也是一种更好的检测孤岛的方法,即使本例中的结果相同。第一个查询会产生这个结果:
name subtitle date num Group_Number
ABC excel 2018-07-07 0 1
ABC excel 2018-08-08 0 1
ABC ppt 2018-09-09 1 2
ABC ppt 2018-10-10 0 2
ABC excel 2018-11-11 1 3
ABC ppt 2018-12-12 1 4
DEF ppt 2018-12-31 0 1
当在边界处检测到字幕中断 除外时,查询发出 1
。
第二个查询returns:
name subtitle date num Group_Number
ABC excel 2018-07-07 1 1
ABC excel 2018-08-08 0 1
ABC ppt 2018-09-09 1 2
ABC ppt 2018-10-10 0 2
ABC excel 2018-11-11 1 3
ABC ppt 2018-12-12 1 4
DEF ppt 2018-12-31 1 1
在这种情况下,每次更改都会发出 1
,包括边界