如何从日期范围中找到可用的日期范围

时间:2018-03-21 06:54:29

标签: sql sql-server

Sql Server

我已经从酒店房间管理系统预订数据中添加了预订。我希望sql查询检索房间可用的日期范围,我也希望找到具体的日期范围

1 个答案:

答案 0 :(得分:0)

您可以使用以下内容。这不是一个简单的查询,我会尽量解释。

  1. 使用递归CTE生成从指定开始日期到指定结束日期的日期。
  2. 将每个日期加入您表格中可能包含的不同房间ID,以创建所有可能的可用日期。
  3. 确定每个房间的日期不可用。
  4. 通过加入所有可能的可用日期并删除不可用的日期来确定每个房间的可用日期(第2点与第3点)。
  5. 确定如何按每个范围进行分组(我使用ROW_NUMBERDENSE_RANK
  6. 以间隔显示每个房间的结果。
  7. 脚本:

    -- Period to consider
    DECLARE @StartDate DATE = '2018-06-20'
    DECLARE @EndDate DATE = '2018-09-01'
    
    ;WITH GeneratedDates AS
    (
        SELECT
            GeneratedDate = @StartDate
    
        UNION ALL
    
        SELECT
            GeneratedDate = DATEADD(DAY, 1, G.GeneratedDate)
        FROM
            GeneratedDates AS G
        WHERE
            G.GeneratedDate < @EndDate
    ),
    ExistingRooms AS
    (
        SELECT DISTINCT
            RoomId
        FROM
            HotelReservation.dbo.Reservation AS R
    ),
    UnavailableDatesByRoom AS
    (
        SELECT DISTINCT
            R.RoomID,
            UnavailableDate = G.GeneratedDate
        FROM
            HotelReservation.dbo.Reservation AS R
            INNER JOIN GeneratedDates AS G ON G.GeneratedDate BETWEEN R.CheckIn AND R.CheckOut
    ),
    AvailableDaysByRoom AS
    (
        SELECT
            AvailableDate = G.GeneratedDate,
            E.RoomID,
            DateRanking = ROW_NUMBER() OVER (PARTITION BY E.RoomID ORDER BY G.GeneratedDate ASC)
        FROM
            GeneratedDates AS G
            CROSS JOIN ExistingRooms AS E
        WHERE
            NOT EXISTS (
                SELECT
                    'unavailable date for that room'
                FROM
                    UnavailableDatesByRoom AS U
                WHERE
                    U.RoomID = E.RoomID AND
                    G.GeneratedDate = U.UnavailableDate)
    ),
    AvailableDaysByRoomGroupings AS
    (
        SELECT
            A.*,
            MagicRanking = DENSE_RANK() OVER (PARTITION BY A.RoomID ORDER BY DateRanking - DATEDIFF(DAY, '2010-01-01', A.AvailableDate))
        FROM
            AvailableDaysByRoom AS A
    )
    SELECT
        G.RoomID,
        FirstAvailableStartDate = MIN(G.AvailableDate),
        LastAvailableStartDate = MAX(G.AvailableDate)
    FROM
        AvailableDaysByRoomGroupings AS G
    GROUP BY
        G.RoomID,
        G.MagicRanking
    ORDER BY
        G.RoomID,
        FirstAvailableStartDate
    OPTION
        (MAXRECURSION 32000)