背景(非常简化): 我有一个横幅空间,我在网站上出售。可以为给定的开始和结束日期预订横幅,此横幅不能重复预订。横幅可以在一年内多次预订,但在同一天不得超过一次。
我的问题: 保存预订时,用户输入开始/结束日期,现在可以在此开始/结束日期内多次预订横幅,我想自动预订开始/结束日期内的任何免费日期。
一个例子:
s|aaaaaaa|s1------e1|aaaaaaaaa|s2------e2|aaaaaa|e
s / e =用户输入的预订日期。 s1 - e1 =首次预订。 s2 - e2 =第二次预订。 aaa .. =可用日期范围。
在tsql中我想计算aaa的开始/结束日期..(可用日期范围)。然后将它们插入预订表。
预订表如下:
BookingId------BannerId-----StartDate-----ExpiryDate
000000001------00000001-----2012-11-01----2012-11-05
000000002------00000001-----2012-11-10----2012-11-15
000000003------00000001-----2012-11-16----2012-11-20
000000004------00000001-----2012-12-01----2012-12-05
因此,如果用户输入的开始日期为2012-11-04,结束日期为2012-12-10。可用日期为.. 2012-11-06至2012-11-09,2012-11-21至2012-11-30,2012-12-06-2012-12-10。
感谢您提供有关如何执行此操作的任何建议。
答案 0 :(得分:1)
这似乎可以解决问题:
(所有一个脚本,但拆分以便您可以看到每个部分)数据设置:
declare @Bookings table (
BookingId char(9) not null,
BannerId char(8) not null,
StartDate date not null,
ExpiryDate date not null
)
insert into @Bookings (BookingId,BannerId,StartDate,ExpiryDate) values
('000000001','00000001','20121101','20121105'),
('000000002','00000001','20121110','20121115'),
('000000003','00000001','20121116','20121120'),
('000000004','00000001','20121201','20121205')
输入:
declare @StartDate date
declare @EndDate date
select @StartDate = '20121104',@EndDate = '20121210'
查询:
;With Ordered as (
select *,ROW_NUMBER() OVER (PARTITION BY BannerID ORDER BY StartDate) as rn
from @Bookings
), FreePeriods as (
select
o1.BannerId,
DATEADD(day,1,o1.ExpiryDate) as StartDate,
DATEADD(day,-1,o2.StartDate) as EndDate
from
Ordered o1
inner join
Ordered o2
on
o1.BannerId = o2.BannerId and
o1.rn = o2.rn - 1
where
DATEDIFF(day,o1.ExpiryDate,o2.StartDate) >= 3
union all
select
BannerId,'00010101',DATEADD(day,-1,MIN(StartDate)) from @Bookings group by BannerID
union all
select
BannerID,DATEADD(day,1,MAX(ExpiryDate)),'99991231' from @Bookings group by BannerID
)
select
BannerID,
CASE WHEN @StartDate > StartDate then @StartDate ELSE StartDate END as StartDate,
CASE WHEN @EndDate < EndDate then @EndDate ELSE EndDate END as EndDate
from
FreePeriods fp
where
fp.EndDate >= @StartDate and
fp.StartDate <= @EndDate
基本上,我将预订的日期组织成连续的对,然后使用每对构建它们之间存在的自由时间段。我还伪造了两个时期 - 一个从最开始预订到最早预订,一个从最新预订到结束时间。
然后,在最后一个查询中,查找与请求日期重叠的句点,并使用一些CASE
表达式来修剪超出请求日期的句点。