如何查询酒店数据库以返回对连续三晚可用的单人房的查询?

0kjbasz6  于 2021-06-19  发布在  Mysql
关注(0)|答案(5)|浏览(366)

我试图找到以下问题的答案:一位顾客想要一间连续住三晚的单人房。找到2016年12月的第一个可用日期。
根据这个问题,这应该是正确的答案。但我不知道怎么解决。

  1. +-----+------------+
  2. | id | MIN(i) |
  3. +-----+------------+
  4. | 201 | 2016-12-11 |
  5. +-----+------------+

链接来自第14题。
这是数据库的er图:

cbjzeqam

cbjzeqam1#

我的解决方案是将问题分成两部分(最后是两个查询连接在一起)。可能不是最有效的,但解决方案是正确的。
1) 在单人房中,查看最后一个退房日期,看哪个房间先空置(即本月剩余时间内不再有预订)2)在当前预订之间办理入住手续-看他们之间是否有3天的间隔3)将这些房间放在一起-抓住最短时间

  1. WITH subquery AS( -- existing single-bed bookings in Dec
  2. SELECT room_no, booking_date,
  3. DATE_ADD(booking_date, INTERVAL (nights-1) DAY) AS last_night
  4. FROM booking
  5. WHERE room_type_requested='single' AND
  6. DATE_ADD(booking_date, INTERVAL (nights-1) DAY)>='2016-12-1' AND
  7. booking_date <='2016-12-31'
  8. ORDER BY room_no, last_night)
  9. SELECT room_no, MIN(first_avail) AS first_avail --3) join the 2 together
  10. FROM(
  11. -- 1) check the last date the room is booked in December (available after)
  12. SELECT room_no, MIN(first_avail) AS first_avail
  13. FROM(
  14. SELECT room_no, DATE_ADD(MAX(last_night), INTERVAL 1 DAY) AS first_avail
  15. FROM subquery q3
  16. GROUP BY 1
  17. ORDER BY 2) AS t2
  18. UNION
  19. -- 2) check if any 3-day exist in between reservations
  20. SELECT room_no, DATE_ADD(MIN(end2), INTERVAL 1 DAY) AS first_avail
  21. FROM(
  22. SELECT q1.booking_date AS beg1, q1.room_no, q1.last_night AS end1,
  23. q2.booking_date AS beg2, q2.last_night AS end2
  24. FROM subquery q1
  25. JOIN subquery q2
  26. ON q1.room_no = q2.room_no AND q2.booking_date > q1.last_night
  27. GROUP BY 2,1
  28. ORDER BY 2,1) AS t
  29. WHERE beg2-end1 > 3) AS inner_t
展开查看全部
mzmfm0qo

mzmfm0qo2#

如果没有日历桌,这似乎很难做到——因为一个合适的房间在一个月内可能根本没有预订。如果没有任何预订,这个月就没有记录了。

  1. select r.id, dte
  2. from rooms r cross join
  3. (select date('2018-12-01') as dte union all
  4. select date('2018-12-02') as dte union all
  5. . . .
  6. select date('2018-12-32') as dte
  7. ) d
  8. where not exists (select 1 from bookings b where b.room_no = r.id and b.booking_date = d.dte) and
  9. not exists (select 1 from bookings b where b.room_no = r.id and b.booking_date = d.dte + interval 1 day) and
  10. not exists (select 1 from bookings b where b.room_no = r.id and b.booking_date = d.dte + interval 2 day)
  11. order by d.dte
  12. limit 1;

这是假设 booking_date 是停留的开始。你需要提供“单人房”的逻辑。

yftpprvb

yftpprvb3#

  1. select distinct top 1 alll.i,alll.room_no,
  2. case
  3. when (select count(*) from booking where room_no = alll.room_no and booking_date between dateadd(day,1,alll.i) and dateadd(day,3,alll.i)) > 0 then 'Y'
  4. else 'N'
  5. end as av3
  6. from
  7. (select c.i,b.room_no,b.booking_date
  8. from calendar c cross join booking b
  9. where month(c.i) = 12 and year(c.i) = 2016 and b.room_type_requested = 'single'
  10. ) as alll
  11. join
  12. (
  13. select distinct c.i, b.room_no
  14. from calendar c join booking b
  15. on c.i between b.booking_date and DATEADD(day,b.nights-1,b.booking_date)
  16. where month(c.i) = 12 and year(c.i) = 2016 and b.room_type_requested = 'single'
  17. ) as booked
  18. on alll.i = booked.i
  19. and alll.room_no <> booked.room_no
  20. order by 1

这很管用。这有点复杂,但基本上首先检查所有已预订的房间,然后在每月的每一天对未预订的房间进行比较,直到接下来的3天。

展开查看全部
t9eec4r0

t9eec4r04#

很抱歉,我对这种查询有点生疏,我不能保证所有语法都正确无误,但我认为下面的方法可能会奏效:

  1. SELECT id, DATE_ADD(b.booking_date, INTERVAL (end_date + 1 DAY) as date
  2. FROM (
  3. SELECT r.id, STR_TO_DATE('2016-01-01', '%Y-%m-%d') as start_of_month, b.booking_date as start_date, DATE_ADD(b.booking_date, INTERVAL (nights - 1) DAY) as end_date
  4. FROM room r
  5. LEFT JOIN booking b ON r.id = b.room_no
  6. ORDER BY r.id, b.booking_date
  7. ) as room_bookings
  8. WHERE DATE_DIFF(room_bookings.start_of_month, room_bookings.start_date) >= 3
  9. OR DATE_DIFF(room_bookings.end_date, (
  10. SELECT b2.booking_date FROM booking b2
  11. WHERE b2.room_no = room_bookings.id AND b2.booking_date > room_bookings.start_date
  12. ORDER BY b2.booking_date LIMIT 1)
  13. ) >= 3

事实上,现在我把这些都打出来了,您也许可以调整主查询的where,这样您甚至不需要room\u bookings子选择。希望这会有所帮助,而且不会太离题。

n3ipq98p

n3ipq98p5#

这在概念上是有效的,因为第一个可用日期应该始终是前一个预订的结束日期。

  1. SELECT MIN(DATE_ADD(a.booking_date, INTERVAL nights DAY)) AS i
  2. FROM booking AS a
  3. WHERE DATE_ADD(a.booking_date, INTERVAL nights DAY)
  4. >= '2016-12-01'
  5. AND room_type_requested = 'single'
  6. AND NOT EXISTS
  7. (SELECT 1 FROM booking AS b
  8. WHERE b.booking_date BETWEEN
  9. DATE_ADD(a.booking_date, INTERVAL nights DAY)
  10. AND DATE_ADD(a.booking_date, INTERVAL nights+2 DAY)
  11. AND a.room_no = b.room_no)

相关问题