英文:
Assign group to rows by 7 days window with breaks
问题
以下是您提供的内容的中文翻译:
我有一张填满日期的表格,我想将它们分成持续7天的块。我还希望注意块之间的间隙,并将任何在前一个块结束之后出现的日期视为7天周期的开始。
以下是我期望的输出示例:
日期 块
---------------------
2023-03-02 1
2023-03-03 1
2023-03-04 1
2023-03-10 2
2023-03-16 2
2023-04-04 3
2023-05-02 4
2023-05-05 4
我有一个使用while语句的算法。但在批量情况下,它运行得太慢了。是否有其他方法?
create table #dates_to_assign (
[日期] date
)
insert into #dates_to_assign values
('2023-03-02'), ('2023-03-03'), ('2023-03-04'), ('2023-03-10'),
('2023-03-16'), ('2023-04-04'), ('2023-05-02'), ('2023-05-05')
create table #dates_assigned (
[日期] date,
[块] int
)
declare @curr_date date = (select min([日期]) from #dates_to_assign)
declare @block int = 1
WHILE EXISTS(SELECT TOP 1 * from #dates_to_assign)
BEGIN
insert into #dates_assigned
select [日期], [块] = @block
from #dates_to_assign
where DATEDIFF(DAY, @curr_date, [日期]) < 7
delete from #dates_to_assign
where DATEDIFF(DAY, @curr_date, [日期]) < 7
set @curr_date = (select min([日期]) from #dates_to_assign)
set @block = @block + 1
END
select *
from #dates_assigned
英文:
I have a table filled with dates and I want to group them in 7 day lasting blocks.
I also want to mind the gaps between the blocks and treat any date, that comes after preceding block end, as a start of a 7 day period.
Below is my desired output example
Date Block
---------------------
2023-03-02 1
2023-03-03 1
2023-03-04 1
2023-03-10 2
2023-03-16 2
2023-04-04 3
2023-05-02 4
2023-05-05 4
I have an algorithm using the while statement. But its not usable in batch situations as it runs way too slow. Is there some other way?
create table #dates_to_assign (
[Date] date
)
insert into #dates_to_assign values
('2023-03-02'), ('2023-03-03'), ('2023-03-04'), ('2023-03-10'),
('2023-03-16'), ('2023-04-04'), ('2023-05-02'), ('2023-05-05')
create table #dates_assigned (
[Date] date,
[Block] int
)
declare @curr_date date = (select min([Date]) from #dates_to_assign)
declare @block int = 1
WHILE EXISTS(SELECT TOP 1 * from #dates_to_assign)
BEGIN
insert into #dates_assigned
select [Date], [Block] = @block
from #dates_to_assign
where DATEDIFF(DAY, @curr_date, [Date]) < 7
delete from #dates_to_assign
where DATEDIFF(DAY, @curr_date, [Date]) < 7
set @curr_date = (select min([Date]) from #dates_to_assign)
set @block = @block + 1
END
select *
from #dates_assigned
答案1
得分: 1
I suspect you need to use recursive CTE for this:
with data as (
select *
, row_number() over(order by date) as counter
from
(
VALUES (N'2023-03-02','1')
, (N'2023-03-03','1')
, (N'2023-03-04','1')
, (N'2023-03-10','2')
, (N'2023-03-16','2')
, (N'2023-04-04','3')
, (N'2023-05-02','4')
, (N'2023-05-05','4')
, (N'2023-05-06','4')
, (N'2023-05-07','4')
, (N'2023-05-09','4')
, (N'2023-05-10','5')
) t (Date ,Block )
)
, blocks as (
select date, counter, date as startblock, 1 as block
from data
where counter = 1
union all
select d.date, d.counter
, case when datediff(day, startblock, d.date) < 7 then b.startblock else d.date end
, case when datediff(day, startblock, d.date) < 7 then b.block else b.block + 1 end
from blocks b
inner join data d
ON d.counter = b.counter + 1
)
select *
from blocks
option (maxrecursion 0);
这段代码通过递归公共表达式(CTE)按照日期和计数器将每个日期"循环"并在每次超出7天期间时重置起始日期。为了提高性能,最好将计数器与索引材料化,但不确定是否可行。
英文:
I suspect you need to use recursive cte for this:
with data as (
select *
, row_number() over(order by date) as counter
from
(
VALUES (N'2023-03-02','1')
, (N'2023-03-03','1')
, (N'2023-03-04','1')
, (N'2023-03-10','2')
, (N'2023-03-16','2')
, (N'2023-04-04','3')
, (N'2023-05-02','4')
, (N'2023-05-05','4')
, (N'2023-05-06','4')
, (N'2023-05-07','4')
, (N'2023-05-09','4')
, (N'2023-05-10','5')
) t (Date ,Block )
)
, blocks as (
select date, counter, date as startblock, 1 as block
from data
where counter = 1
union all
select d.date, d.counter
, case when datediff(day, startblock, d.date) < 7 then b.startblock else d.date end
, case when datediff(day, startblock, d.date) < 7 then b.block else b.block + 1 end
from blocks b
inner join data d
ON d.counter = b.counter + 1
)
select *
from blocks
option (maxrecursion 0);
This "loops" each date by counter and reset the start date each time you leave the 7 day period.
For performance you'd do well to materialize the counter with index, but not sure if it's possible.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论