I have a table that contains bookings for borrowing assets:
--------
Bookings
--------
BookingID AssetNo Start End Status
--------- ------- ----------------------- ----------------------- ------
1 1 2023-05-31 00:00:00.000 2023-05-31 01:00:00.000 Overdue
2 1 2023-05-31 01:00:00.000 2023-05-31 02:00:00.000 Booked
3 2 2023-05-31 01:00:00.000 2023-05-31 02:00:00.000 InUse
4 2 2023-05-31 02:00:00.000 2023-05-31 03:00:00.000 Booked
5 2 2023-05-31 03:00:00.000 2023-05-31 04:00:00.000 Booked
For each asset, I want to select the booking that the asset is currently being borrowed against, at the current time, and the next booking that exists for the asset after that, in time order (if present).
For example, using the data above, when the current time is 2023-05-31 01:30:00.000
:
AssetNo 1
is currently being borrowed againstBookingID 1
, as the asset wasn't returned in time, and isOverdue
against the booking (which is in the past).AssetNo 2
is currently being borrowed againstBookingID 3
, as the asset isInUse
against the booking (which is at the present time)
I want a query that will select the following from the example data set, when current time = 2023-05-31 01:30:00.000
:
BookingID AssetNo Start End Status Active
--------- ------- ----------------------- ----------------------- ------ ------
1 1 2023-05-31 00:00:00.000 2023-05-31 01:00:00.000 Overdue True
2 1 2023-05-31 01:00:00.000 2023-05-31 02:00:00.000 Booked False
3 2 2023-05-31 01:00:00.000 2023-05-31 02:00:00.000 InUse True
4 2 2023-05-31 02:00:00.000 2023-05-31 03:00:00.000 Booked False
I can select the currently active bookings like this:
DECLARE @UTCNow DATETIME;
SET @UTCNow = '2023-05-31 01:30:00.000';
SELECT * FROM (
SELECT
b.*
,RANK() OVER (PARTITION BY b.AssetNo ORDER BY [Start] ASC) AS time_order
FROM Bookings b
WHERE (b.[End] < @UTCNow AND b.Status = 'Overdue') -- past booking that started but hasn't completed
OR (b.[Start] <= @UTCNow AND b.[End] > @UTCNow) -- booking that occurs at the present time
) AS b2
WHERE b2.time_order = 1
How can I also select the booking that follows the currently active booking, and for each asset, set which one is the active booking ( Active = True
), and which is a subsequent booking for the same Asset ( Active = False
)? I can use transact SQL but would prefer to use ANSI.
Update
I've created the following SQL Fiddle that sets up the example data set. I've begun outlining a different possible approach i.e. selecting the start time of the currently active booking for each asset, and selecting the first 2 bookings for each asset from that time, ordered by Start
ASC
:
http://sqlfiddle.com/#!18/f51f5/7
2条答案
按热度按时间xoefb8l81#
I solved it like this:
http://sqlfiddle.com/#!18/f51f5/32
mlnl4t2r2#
Not completely clear on your expectation of the final output. Perhaps you'd like columns BookingID, AssetNo, Start, End, Status, Active, Start_Next, (and End_Next), and BookingID_Next in each output row? And I assume booking IDs are unique.
Some questions I have:
Following (based on aforementioned assumptions) is my suggestion:
You can add additional data points in SELECT, and ORDER BY at the end to further specify how you'd like the output to be arranged.