1

背景 (非常に簡略化): Web サイトで販売するバナー スペースがあります。バナーは特定の開始日と終了日に予約できますが、このバナーを二重に予約することはできません。バナーは 1 年に複数回予約できますが、同じ日に複数回予約することはできません。

私の問題: 予約を保存するときに、ユーザーが開始日/終了日を入力すると、この開始日/終了日内にバナーが複数回予約される可能性があり、開始日/終了日内の空き日を自動的に予約したい.

例:

s|aaaaaaa|s1------e1|aaaaaaaaa|s2------e2|aaaaaa|e

s / e = ユーザーが入力した予約日。 s1 - e1 = 最初の予約。 s2 - e2 = 2 番目の予約。 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

これはトリックを行うようです:

(すべて 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

基本的に、予約した日付を連続したペアに編成し、各ペアを使用してその間に存在する無料期間を構築します。また、さらに 2 つの期間を偽造します。1 つは時間の開始から最も早い予約まで、もう 1 つは最新の予約から時間の終わりまでです。

次に、最後のクエリで、要求された日付と重複する期間を見つけ、いくつかのCASE式を使用して、要求された日付を超える期間をトリミングします。

于 2012-11-19T11:27:53.637 に答える