-
Tạo danh sách tất cả các ranh giới đặt phòng (tức là ngày bắt đầu và ngày kết thúc) xảy ra trong khoảng thời gian mong muốn:
SELECT date_start AS boundary FROM bookings WHERE date_start BETWEEN @start AND @end UNION SELECT date_end FROM bookings WHERE date_end BETWEEN @start AND @end
-
Thêm vào đó là ranh giới xảy ra ngay trước khoảng thời gian mong muốn:
-- [ from part 1 above ] UNION SELECT MAX(boundary) FROM ( SELECT MAX(date_start) AS boundary FROM bookings WHERE date_start <= @start UNION ALL SELECT MAX(date_end) FROM bookings WHERE date_end <= @end ) t
-
Thực hiện liên kết bên ngoài giữa kết quả này và
bookings
bảng, giữ tất cả các ranh giới nhưng chỉ bao gồm một lượt đặt chỗ nếu nó góp phần vào số lượng người đồng thời sau ranh giới:FROM bookings RIGHT JOIN ( -- [ from part 2 above ] ) t ON date_start <= boundary AND boundary < date_end
-
Tính tổng số người ở mỗi ranh giới:
SELECT IFNULL(SUM(quantity),0) AS simultaneous_people -- [ from part 3 above ] GROUP BY boundary
-
Tìm giá trị tối đa và tối thiểu:
SELECT MIN(simultaneous_people), MAX(simultaneous_people) FROM ( -- [ from part 4 above ] ) t
Kết hợp tất cả lại với nhau:
SELECT MIN(simultaneous_people),
MAX(simultaneous_people)
FROM (
SELECT IFNULL(SUM(quantity),0) AS simultaneous_people
FROM bookings RIGHT JOIN (
SELECT date_start AS boundary
FROM bookings
WHERE date_start BETWEEN @start AND @end
UNION
SELECT date_end
FROM bookings
WHERE date_end BETWEEN @start AND @end
UNION
SELECT MAX(boundary)
FROM (
SELECT MAX(date_start) AS boundary
FROM bookings
WHERE date_start <= @start
UNION ALL
SELECT MAX(date_end)
FROM bookings
WHERE date_end <= @end
) t
) t ON date_start <= boundary AND boundary < date_end
GROUP BY boundary
) t
Xem nó trên sqlfiddle .