3

昨日の質問に続いて、ラップトップのロールアウト「予約システム」の「利用可能な」日付の範囲を返す必要があります。ユーザーがスロットを予約できる可能性のある日付の表を作成したいと考えています。各日付について、スロットの可能な合計数を確認し、すでに予約されているスロットの数を差し引きます。

ロジックは次のとおりです。

  • 技術者は 1 日に 3 台のラップトップを構築できます。
  • いつでも 1 人、2 人、または 3 人の技術者が対応可能です。
  • 行われた予約を保持するテーブル
  • 可能なすべての日付の表は必要ありません。その場で計算したい

関連するテーブルは次のとおりです。

tl_sb_slotBooking これには、すでに行われた予約が含まれます

ここに画像の説明を入力

tl_sb_availabilityPeriods これは、特定の日に利用可能なスロットの総数を計算するために使用されます ここに画像の説明を入力

スロットの固定最大数 (この場合は 3) で日付のリストを戻すことができます。

    DECLARE @startDate DATE
    DECLARE @endDate DATE

    SET @startDate = GETDATE()
    SET @endDate = DATEADD(m,3,@startDate)
    ;
    WITH dates(Date) AS 
    (
       SELECT @startdate as Date
       UNION ALL
       SELECT DATEADD(d,1,[Date])
         FROM dates 
         WHERE DATE < @enddate
    )

    SELECT Date
      FROM dates 
    EXCEPT
    SELECT date
    FROM tl_sb_booking
    GROUP BY date
    HAVING COUNT(date) >= 3

ただし、最大数は常に 3 とは限らず、日によって異なります。

特定の日に可能な最大スロットを見つけることができます。

    DECLARE @myDate DATETIME = '2013-06-22'

    SELECT SUM(laptopsPerDay) AS totalSlots
       FROM tl_sb_technicianAvailability
       WHERE startDate <= @myDate AND endDate >= @myDate
       AND availabiltyStateID=3

2013 年 6 月 22 日に利用可能なスロットの総数として 6 が返されます。(availabilityStateID フィールドは、使用可能/使用不可などを格納するために使用されます。)

だから、私が立ち往生しているビットは、2つを組み合わせることです。

私が欲しいのは、可能な日付ごとです。すでに予約されているスロットの数がその日の可能なスロットの数よりも少ない場合は、返されるテーブルに追加します(そうでない場合はしないでください)。

4

2 に答える 2

2

まず、小さなリストしか生成していませんが、CTE を使用してシーケンシャル リストを生成するとパフォーマンスが低下するため、避けるのが最善です。

このためにMaster..spt_values、番号の連続したリストにシステム テーブルを使用しますが、文書化されていないシステム テーブルの使用が心配な場合は、上記のリンクに他の方法があります。

私が最初に行うことは、技術者の利用可能日を 1 日ごとの行に分割することです。これにより、必要な期間の一部しか利用できない技術者が可能になります (たとえば、6 月 18 日からクエリを実行する場合は、テーブルのスクリーン ショットから)。 6 月 26 日まで、投稿したクエリを使用して利用可能な技術者は表示されません):

SELECT  Date = DATEADD(DAY, spt.Number, ta.StartDate),
        ta.TechnicianID,
        ta.LapTopsPerDay
FROM    tl_sb_technicianAvailability ta
        INNER JOIN Master..spt_values spt
            ON spt.Type = 'P'
            AND spt.Number BETWEEN 0 AND DATEDIFF(DAY, ta.startDate, ta.EndDate)

This would simply turn:

TechnicianID    StartDate   EndDate     LapTopsPerDay
1               20130620    20130624    3

の中へ

Date        TechnicianID    LapTopsPerDay
20130620    1               3
20130621    1               3
20130622    1               3
20130623    1               3
20130624    1               3

次に、このリストを必要な日付範囲に制限し、技術レベルでは必要ないため、実行可能なラップトップの合計を合計できます。

WITH ExplodedAvailability AS
(       SELECT  Date = DATEADD(DAY, spt.Number, ta.StartDate),
                ta.TechnicianID,
                ta.LapTopsPerDay
        FROM    tl_sb_technicianAvailability ta
                INNER JOIN Master..spt_values spt
                    ON spt.Type = 'P'
                    AND spt.Number BETWEEN 0 AND DATEDIFF(DAY, ta.startDate, ta.EndDate)
)
SELECT  Date, TotalLaptops = SUM(LapTopsPerDay)
FROM    ExplodedAvailability
WHERE   Date >= @StartDate
AND     Date < @EndDate
GROUP BY Date;

最後に、予約テーブルに LEFT JOIN して、1 日あたりの利用可能なスロットを取得できます。

WITH ExplodedAvailability AS
(       SELECT  Date = DATEADD(DAY, spt.Number, ta.StartDate),
                ta.TechnicianID,
                ta.LapTopsPerDay
        FROM    tl_sb_technicianAvailability ta
                INNER JOIN Master..spt_values spt
                    ON spt.Type = 'P'
                    AND spt.Number BETWEEN 0 AND DATEDIFF(DAY, ta.startDate, ta.EndDate)
), Availability AS
(   SELECT  Date, TotalLaptops = SUM(LapTopsPerDay)
    FROM    ExplodedAvailability
    WHERE   Date >= @StartDate
    AND     Date < @EndDate
    GROUP BY Date
), Bookings AS
(   SELECT  Date, SlotsBooked = COUNT(*)
    FROM    tl_sb_booking
    GROUP BY Date
)
SELECT  Availability.Date,
        Availability.TotalLaptops,
        RemainingSlots = Availability.TotalLaptops - ISNULL(Bookings.SlotsBooked, 0)
FROM    Availability
        LEFT JOIN Bookings
            ON Bookings.Date = Availability.Date;

あなたが求めているのは、次の利用可能な日に予約を追加することだと思うので、これを行うためのクエリは次のようになります。

DECLARE @UserID INT = 1;

WITH ExplodedAvailability AS
(       SELECT  Date = DATEADD(DAY, spt.Number, ta.StartDate),
                ta.TechnicianID,
                ta.LapTopsPerDay
        FROM    tl_sb_technicianAvailability ta
                INNER JOIN Master..spt_values spt
                    ON spt.Type = 'P'
                    AND spt.Number BETWEEN 0 AND DATEDIFF(DAY, ta.startDate, ta.EndDate)
), Availability AS
(   SELECT  Date, TotalLaptops = SUM(LapTopsPerDay)
    FROM    ExplodedAvailability
    WHERE   Date >= CAST(GETDATE() AS DATE)
    GROUP BY Date
), Bookings AS
(   SELECT  Date, SlotsBooked = COUNT(*)
    FROM    tl_sb_booking
    GROUP BY Date
)
INSERT tl_sb_slotBooking (UserID, Date)
SELECT  @UserID, MIN(Availability.Date)
FROM    Availability
        LEFT JOIN Bookings
            ON Bookings.Date = Availability.Date
WHERE   Availability.TotalLaptops > ISNULL(Bookings.SlotsBooked, 0)
于 2013-06-20T12:20:28.690 に答える