1

背景(非常简化):我有在网站上出售的横幅空间。可以为给定的开始和结束日期预订横幅,此横幅不能重复预订。横幅可以在一年内多次预订,但在同一日期不得超过一次。

我的问题:保存预订时,用户输入开始/结束日期,现在横幅可能会在此开始/结束日期内多次预订,我想在开始/结束日期内自动预订任何免费日期。

一个例子:

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 月 4 日的开始日期和 2012 年 12 月 10 日的结束日期。可用日期为.. 2012-11-06 至 2012-11-09、2012-11-21 至 2012-11-30、2012-12-06-2012-12-10。

感谢您提供有关如何执行此操作的任何建议。

4

1 回答 1

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表达式来修剪超出请求日期的时段。

于 2012-11-19T11:27:53.637 回答