这是参考以下问题
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
答案 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
有什么想法吗?