使用新的开始日期和结束日期为每个值创建剧集

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用新的开始日期和结束日期为每个值创建剧集相关的知识,希望对你有一定的参考价值。

这是参考下面的问题

Loop through each value to the seq num

但现在客户希望以不同的方式查看数据并为此问题启动新线程。以下是要求。

This is the data .
ID  seqNum  DOS         Service End Date
1   1       1/1/2017    1/15/2017
1   2       1/16/2017   1/16/2017
1   3       1/17/2017   1/21/2017
1   4       1/22/2017   2/13/2017
1   5       2/14/2017   3/21/2017
1   6       2/16/2017   3/21/2017



Expected outPut:

ID    SeqNum      DOSBeg       DOSEnd
1      1          1/1/2017     1/30/2017
1      2          1/31/2017    3/1/2017
1      3          3/2/2017     3/31/2017

For each DOSBeg, add 29 and that is DOSEnd. then Add 1 to DOSEnd (1/31/2017) is new DOSBeg. 
Now add 29 to (1/31/2017) and that is  3/1/2017 which is DOSEnd . Repeat this untill DOSend >=Max End Date i.e 3/21/2017.

基本上,每个ID我们需要29天的剧集。

我试过这个代码,它给了我重复。

with cte as (
      select  ID, minDate as DOSBeg,dateadd(day,29,mindate) as DOSEnd
     from #temp 
      union all
      select  ID,dateadd(day,1,DOSEnd) as DOSBeg,dateadd(day,29,dateadd(day,1,DOSEnd)) as DOSEnd 
      from cte
     )
select  ID,DOSBeg,DOSEnd
from cte
OPTION (MAXRECURSION 0)

Here mindate is Minimum DOS for this ID i.e.  1/1/2017 

我提出了以下逻辑,这对我来说很好。还有比这更好的方法吗?

declare @table table (id int, seqNum int identity(1,1), DOS date, ServiceEndDate date)
insert into @table
values
(1,'20170101','20170115'),
(1,'20170116','20170116'),
(1,'20170117','20170121'),
(1,'20170122','20170213'),
(1,'20170214','20170321'),
(1,'20170216','20170321'),
(2,'20170101','20170103'),
(2,'20170104','20170118')

select * into #temp from @table

--drop table #data
select distinct ID, cast(min(DOS) over (partition by ID) as date) as minDate
,row_Number() over (partition by ID order by ID, DOS) as SeqNum,
DOS,
max(ServiceEndDate) over (partition by ID)as maxDate
into #data 
from #temp



--drop table #StartDateLogic
with cte as 
(select ID,mindate as startdate,maxdate
from #data
union all
select ID,dateadd(day,30,startdate) as startdate,maxdate
from cte
where maxdate >= dateadd(day,30,startdate))
select distinct ID,startdate
into #StartDateLogic
from cte
OPTION (MAXRECURSION 0)

--final Result set
select ID
,ROW_NUMBER() over (Partition by ID order by ID,StartDate) as SeqNum
,StartDate
,dateadd(day,29,startdate) as EndDate
from #StartDateLogic
答案

@scsimon。

如果以下是我的数据集,那么我没有得到ID = 2。我只得到第一个ID = 1。

declare @table table (id int, seqNum int identity(1,1), DOS date, ServiceEndDate date)
insert into @table
values
(1,'20170101','20170115'),
(1,'20170116','20170116'),
(1,'20170117','20170121'),
(1,'20170122','20170213'),
(1,'20170214','20170321'),
(1,'20170216','20170321'),
(2,'20170101','20170103'),
(2,'20170104','20170118')


declare @startDate date = (select min(DOS) from @table)
declare @endDate date = (select max(ServiceEndDate) from @table)


;with dates as(
    select top 1 id, seqnum, DOSBeg = DOS, DOSEnd = dateadd(day,29,DOS)
    from @table
    order by seqNum
    union all
    select id, seqNum + 1, DOSBeg = dateadd(day,1,DOSEnd), DOSEnd = dateadd(day,29,dateadd(day,1,DOSEnd))
    from dates
    where DOSEnd <= @endDate)

select * 
from dates


with my given data, 
i would like to have ID=1 along with ID=2

ID    SeqNum   DOSBeg     DOSend
2     1        20170101   20170130

有什么想法吗?

另一答案

您使用递归cte在正确的轨道上,但是您忘记了锚点。

declare @table table (id int, seqNum int identity(1,1), DOS date, ServiceEndDate date)
insert into @table
values
(1,'20170101','20170115'),
(1,'20170116','20170116'),
(1,'20170117','20170121'),
(1,'20170122','20170213'),
(1,'20170214','20170321'),
(1,'20170216','20170321'),
(2,'20170101','20170103'),
(2,'20170104','20170118')


;with dates as(
    select top 1 with ties id, seqnum, DOSBeg = DOS, DOSEnd = dateadd(day,29,DOS)
    from @table
    order by row_number() over (partition by id order by seqnum)
    union all
    select t.id, t.seqNum, DOSBeg = dateadd(day,1,d.DOSEnd), DOSEnd = dateadd(day,29,dateadd(day,1,d.DOSEnd))
    from dates d
    inner join @table t on
    d.id = t.id and t.seqNum = d.seqNum + 1
    )


select * 
from dates d
where d.DOSEnd <= (select max(dateadd(month,1,ServiceEndDate)) from @table where id = d.id)
order by id, seqNum

以上是关于使用新的开始日期和结束日期为每个值创建剧集的主要内容,如果未能解决你的问题,请参考以下文章

如何为开始日期和结束日期之间的每个工作日创建多行

在熊猫中传播范围日期

为日期范围选择每个日期并插入

在包含多个开始和日期列表的表中查找日期,如果找到则返回默认值

如何对位于开始日期和结束日期之间的一组值求和?

MS Access:按开始日期和结束日期之间每个月的月份分组