我有两个表:resources
和booking_sums
。我想获取在特定日期范围内的资源,每个日期的所有可用时隙都已被预订满。但这被证明是非常困难的。
我有一个booking sums
表,该表存储日期和每个日期的三个时隙(event_time
)。
booking_sums
--------------
event_date (date)
event_time (1-3)
resource id
sum_booked
free_seats_left
我提供了一个event date
范围,并获得了满足以下条件的资源:
我的问题是,如果只有一个日期符合条件,我仍然会获得资源。
所以,如果我有这些booking_sums:
id | event_date | event_time | resource_id | sum_booked | free_seats_left |
id | 2019-09-18 | 1 | 122 | 250 | 0 |
id | 2019-09-18 | 2 | 122 | 250 | 0 |
id | 2019-09-19 | 1 | 122 | 250 | 0 |
id | 2019-09-19 | 2 | 122 | 250 | 0 |
id | 2019-09-19 | 3 | 122 | 250 | 0 |
日期2019-09-19符合条件,但日期2019-09-18不匹配。因此,如果日期范围中包含2019-09-18,我们就不应该得到该结果-但我仍然可以得到它。 这是我的查询:
SELECT distinct r.* FROM resources r
INNER JOIN bookings_sums bs1
ON r.id = bs1.resource_id
WHERE EXISTS(
SELECT 1 FROM bookings_sums
where event_time = 1
AND resource_id = r.id
AND event_date = bs1.event_date
AND free_seats_left = 0
)
AND EXISTS( SELECT 1 FROM bookings_sums where event_time = 2 AND resource_id = r.id
AND event_date = bs1.event_date AND free_seats_left = 0)
AND EXISTS( SELECT 1 FROM bookings_sums where event_time = 3 AND resource_id = r.id
AND event_date = bs1.event_date AND free_seats_left = 0)
AND bs1.event_date BETWEEN '2019-09-18' AND '2019-09-19'
修改: 这是一个小提琴:sqlfiddle
Edit2 : 从下面建议的有效答案中,我做了一些调整,使其更简单了,似乎可行:
SELECT r.id,
r.title
FROM resources r
INNER JOIN bookings_sums bs
ON r.id = bs.resource_id
AND bs.resource_id = r.id
AND bs.event_date
BETWEEN '2019-09-19' AND '2019-09-19' AND bs.free_seats_left = 0
GROUP BY r.id, r.title
HAVING COUNT(bs.id) = (DATEDIFF('2019-09-19', '2019-09-19') + 1) * 3
(而且我可以使用php代替DATEDIFF并直接输入数字)
答案 0 :(得分:0)
您应该能够执行此操作而无需子查询。
SELECT r.*
FROM resources r
INNER JOIN bookings_sums bs1
ON r.id = bs1.resource_id
AND bs1.resource_id = r.id
AND bs1.event_date = bs1.event_date
AND bs1.free_seats_left = 0
GROUP BY r......
HAVING SUM(bs.id) = 3
AND bs1.event_date BETWEEN '2019-09-18' AND '2019-09-19'
您将需要在GROUP BY查询中指定资源表上的所有列。
或者只进行3次加入
SELECT r.*
FROM resources r
INNER JOIN bookings_sums bs1 ON r.id = bs1.resource_id AND bs1.event_time = 1 AND bs1.resource_id = r.id AND bs1.free_seats_left = 0
INNER JOIN bookings_sums bs2 ON r.id = bs2.resource_id AND bs2.event_time = 2 AND bs2.resource_id = r.id AND bs2.event_date = bs1.event_date AND bs2.free_seats_left = 0
INNER JOIN bookings_sums bs3 ON r.id = bs3.resource_id AND bs3.event_time = 3 AND bs3.resource_id = r.id AND bs3.event_date = bs1.event_date AND bs3.free_seats_left = 0
WHERE bs1.event_date BETWEEN '2019-09-18' AND '2019-09-19'
编辑
这可以为您提供所需的东西,但是必须有一种更整齐的方法。
SELECT id,
title
FROM
(
SELECT r.id,
r.title ,
sub0.day_cnt
FROM resources r
CROSS JOIN
(
SELECT DATEDIFF('2019-09-19', '2019-09-18') + 1 AS day_cnt
) sub0
INNER JOIN bookings_sums bs ON r.id = bs.resource_id AND bs.resource_id = r.id AND bs.event_date BETWEEN '2019-09-18' AND '2019-09-19' AND bs.free_seats_left = 0
GROUP BY r.id, r.title
HAVING COUNT(bs.id) = sub0.day_cnt * 3
) sub1;