我有2张桌子- reservation:
reservation
id | some_other_column ----+------------------ 1 | value 2 | value 3 | value
第二张桌子- reservation_log:
reservation_log
id | reservation_id | change_type ----+----------------+------------- 1 | 1 | create 2 | 2 | create 3 | 3 | create 4 | 1 | cancel 5 | 2 | cancel
我只需要选择未取消的预订(在此示例中仅为ID 3)。我可以轻松地选择带有简单WHERE change_type = cancel条件的已取消,但由于WHERE未在此处取消工作,因此我在努力避免未取消。
WHERE change_type = cancel
WHERE
SELECT * FROM reservation WHERE id NOT IN (select reservation_id FROM reservation_log WHERE change_type = 'cancel')
要么:
SELECT r.* FROM reservation r LEFT JOIN reservation_log l ON r.id = l.reservation_id AND l.change_type = 'cancel' WHERE l.id IS NULL
第一个版本更直观,但是我认为第二个版本通常可以获得更好的性能(假设您在联接中使用的列上有索引)。
第二个版本有效,因为LEFT JOIN返回第一个表中所有行的一行。当ON条件成功,这些行会包括从第二表中的列,就像INNER JOIN。当条件失败时,返回的行将包含NULL第二个表中的所有列。然后,WHERE l.id IS NULL测试将匹配这些行,因此它将查找表之间不匹配的所有行。
LEFT JOIN
ON
INNER JOIN
NULL
WHERE l.id IS NULL