Если бы у нас был только идентификатор бронирования, это было бы довольно просто.Но мы можем получить номер бронирования для [Id]
(я полагаю, это клиент, который забронировал?) С помощью
ceiling(row_number() OVER (PARTITION BY [DateOneRow].[Id] ORDER BY [DateOneRow].[CheckInDate]) / convert(decimal, 2))
row_number() OVER (PARTITION BY [DateOneRow].[Id] ORDER BY [DateOneRow].[CheckInDate])
будет нумеровать строки для [Id]
, заказанного [CheckInDate]
.Каждые две строки (в порядке, определенном [CheckInDate]
) принадлежат одному бронированию.Таким образом, мы можем разделить число на 2 и ceiling()
, чтобы получить номер бронирования, к которому относится строка.
Таким образом, мы можем легко GROUP BY [Id]
и номер бронирования, взяв минимальную дату в качестве времени регистрациии максимум как время оформления заказа.Примените datediff()
к этому, и все готово.
SELECT [X].[Id],
min([X].[CheckInDate]) [CheckInDate],
max([X].[CheckInDate]) [CheckOutDate],
datediff(d, min([X].[CheckInDate]), max([X].[CheckInDate])) [DaysBooked]
FROM (SELECT [DateOneRow].[Id],
[DateOneRow].[CheckInDate],
ceiling(row_number() OVER (PARTITION BY [DateOneRow].[Id]
ORDER BY [DateOneRow].[CheckInDate]) / convert(decimal, 2)) [Booking#]
FROM [DateOneRow]) [X]
GROUP BY [X].[Id],
[X].[Booking#];
(Вы можете рассмотреть возможность использования datediff(d, min([X].[CheckInDate]), max([X].[CheckInDate])) + 1 [DaysBooked]
(обратите внимание на + 1
), если даты включительно.)
db <> fiddle
Но я настоятельно рекомендую пересмотреть этот ужасный дизайн!
Редактировать:
Если [Id]
на самом делеидентификатор бронирования и тот же только для двух строк, принадлежащих одному бронированию, это будет просто GROUP BY
с использованием min()
и max()
.
SELECT [DateOneRow].[Id],
min([DateOneRow].[CheckInDate]) [CheckInDate],
max([DateOneRow].[CheckInDate]) [CheckOutDate],
datediff(d, min([DateOneRow].[CheckInDate]), max([DateOneRow].[CheckInDate])) [DaysBooked]
FROM [DateOneRow]
GROUP BY [DateOneRow].[Id];