编辑我已经在这里设置了一个这样的架构:http://sqlfiddle.com/#!2/0726f2。我试图选择客户3,4,5,6。
考虑一个包含三个表的数据库:
customers
---------
id
seats
-----
id
buyer_id (fk to customers)
flight_id
flights
-------
id
datetime (This is the UTC time of the flight)
我试图在3月份找到没有在任何航班上预订座位的客户。
此查询提供未在任何航班上预订座位的客户列表:
SELECT customers.id, count(seats.id) as seat_count FROM `customers`
LEFT JOIN `seats` ON `seats`.`buyer_id` = `customers`.`id`
LEFT JOIN `flights` ON `flights`.`id` = `seats`.`flight_id`
GROUP BY customers.id
HAVING seat_count=0
我尝试了此查询,以查找未在3月份
SELECT customers.id, count(seats.id) as seat_count FROM `customers`
LEFT JOIN `seats` ON `seats`.`buyer_id` = `customers`.`id`
LEFT JOIN `flights` ON `flights`.`id` = `seats`.`flight_id`
WHERE flights.datetime >= '2014-03-01 00:00:00'
AND flights.datetime <= '2014-04-01 00:00:00'
GROUP BY customers.id
HAVING seat_count=0
但它返回一个空列表。我理解为什么:我在3月份选择了预订座位的客户列表,然后在该列表中找到未预订座位的客户。显然是空集。
同样将此添加到WHERE子句
AND seats.is is null
我无法找到合适的方法来做到这一点。
我试过了:
SELECT customers.id from customers where id not in ([above query])
MySql使用相关的子查询,性能也非常糟糕。因为这包含在一个更大的搜索功能中,所以我无法从另一个方向来到此(例如从座位中选择并从那里开始)。架构更改是不可能的。
感谢。
答案 0 :(得分:1)
这有效:
SELECT customers.id, count(seats.id) as seat_count FROM `seats`
INNER JOIN (SELECT id FROM flights WHERE DATE(flights.datetime) >= '2014-03-01'
AND DATE(flights.datetime) <='2014-04-01') `flights` ON `flights`.`id` = `seats`.`flight_id`
RIGHT JOIN customers ON customers.id=seats.buyer_id
GROUP BY customers.id
HAVING seat_count=0
这里是fiddle
这是另一种方法:
SELECT customers.id FROM customers WHERE id NOT IN (SELECT seats.buyer_id FROM seats
INNER JOIN `flights` ON `flights`.`id` = `seats`.`flight_id`
WHERE flights.datetime >= '2014-03-01 00:00:00'
AND flights.datetime <= '2014-04-01 00:00:00')
答案 1 :(得分:1)
您可以使用NOT EXISTS
之类的
SELECT *
FROM customers
WHERE NOT EXISTS (
SELECT * FROM seats
INNER JOIN flights ON flights.id = seats.flight_id
WHERE flights.datetime >= '2014-03-01 00:00:00'
AND flights.datetime <= '2014-04-01 00:00:00'
AND seats.buyer_id = customers.id
)
here is a corresponding SQLFiddle
顺便说一句,你应该至少在seats.buyer_id
上添加索引,因为这是你需要加入的列。使用命名索引,执行计划看起来并不那么糟糕。