mysql - 使用连接表时查找计数为0

时间:2014-03-20 22:29:52

标签: mysql join

编辑我已经在这里设置了一个这样的架构: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

我无法找到合适的方法来做到这一点。

我试过了:

  • 以任何方式翻转JOIN
  • 在LEFT JOIN语句中使用子查询。表现非常糟糕。
  • 尝试SELECT customers.id from customers where id not in ([above query]) MySql使用相关的子查询,性能也非常糟糕。

因为这包含在一个更大的搜索功能中,所以我无法从另一个方向来到此(例如从座位中选择并从那里开始)。架构更改是不可能的。

感谢。

2 个答案:

答案 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')

fiddle

答案 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上添加索引,因为这是你需要加入的列。使用命名索引,执行计划看起来并不那么糟糕。