在 SQL 数据集中查找酒店至少有一个人入住的最近一段时间

Finding within a SQL dataset the most recent period in which a hotel had at least one person staying

我有数据,其中包括酒店 ID、入住日期和退房日期。我正在尝试查找每个酒店的最近一段时间,在此期间每晚至少有一个人入住该酒店。

下面显示的是一个示例数据集:

CREATE TABLE Occupancy
(
   HotelID    INT,
   PersonID   INT,
   CheckIn  DATE,
   CheckOut DATE
)

INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (1, 1, '20/Jan/2015','22/Jan/2015')
INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (1, 2, '13/Jan/2015','20/Jan/2015')
INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (1, 3, '20/Jan/2015','22/Jan/2015')
INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (1, 4, '12/Jan/2015','13/Jan/2015')
INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (1, 5, '01/Jan/2015','10/Jan/2015')
INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (1, 6, '01/Jan/2015','04/Jan/2015')
INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (2, 7, '10/Jan/2015','20/Jan/2015')
INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (2, 8, '11/Jan/2015','12/Jan/2015')
INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (2, 9, '12/Jan/2015','13/Jan/2015')
INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (2, 10, '12/Jan/2015','13/Jan/2015')
INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (2, 11, '01/Jan/2015','02/Jan/2015')
INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (3, 12, '02/Jan/2015','03/Jan/2015')
INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (3, 13, '04/Jan/2015','05/Jan/2015')
INSERT INTO Occupancy (HotelID, PersonID, CheckIn, CheckOut) VALUES (3, 14, '05/Jan/2015','06/Jan/2015')

我正在尝试创建一个视图,我期望的结果如下:

HotelID     From            To
1           12/Jan/2015     22/Jan/2015
2           10/Jan/2015     20/Jan/2015
3           04/Jan/2015     06/Jan/2015

我怀疑您需要进行递归查询,但我不确定如何进行。我应该补充一点,我正在使用 Microsoft SQL Server 2008 R2。预先感谢您的帮助。

我想我找到了答案,虽然感觉很绕。我怀疑可能有更好的方法。这是:

WITH OverlappingOccupancy
     AS (SELECT *
         FROM   (SELECT Row_number() OVER (PARTITION BY HotelID ORDER BY CheckOut DESC, CheckIN ASC) AS RowNumber,
                        HotelID,
                        CheckIN,
                        CheckOut
                 FROM   Occupancy) AS RankedOccupancy
         WHERE  RowNumber = 1
         UNION ALL
         SELECT *
         FROM   (SELECT Row_number() OVER (PARTITION BY Occupancy.HotelID ORDER BY Occupancy.CheckIN ASC) AS RowNumber,
                        Occupancy.HotelID,
                        Occupancy.CheckIN,
                        Occupancy.CheckOut
                 FROM   Occupancy
                        INNER JOIN OverlappingOccupancy ON OverlappingOccupancy.HotelID = Occupancy.HotelID
                 WHERE  Occupancy.CheckOut >= OverlappingOccupancy.CheckIn
                        AND Occupancy.CheckIn < OverlappingOccupancy.CheckIn) AS RankedOccupancy
         WHERE  RowNumber = 1)
SELECT HotelID,
       Min(CheckIn) AS FromCheckIn,
       Max(CheckOut) AS ToCheckOut
FROM   OverlappingOccupancy
GROUP  BY HotelID