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

时间:2018-08-17 16:11:42

标签: sql sql-server sql-server-2012

这是参考以下问题

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

2 个答案:

答案 0 :(得分:0)

您正处于递归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

答案 1 :(得分:0)

@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

有什么想法吗?