我有2张桌子 - reservation
:
id | some_other_column
----+------------------
1 | value
2 | value
3 | value
和第二个表 - 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
条件,但我正在努力与NOT取消,因为简单的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
测试匹配这些行,因此它找到表之间没有匹配的所有行。
只是为了完整(我真的相信它更适合),我鼓励你使用一个简单的NOT EXISTS
。
SELECT * FROM reservation R
WHERE NOT EXISTS (
SELECT 1 FROM reservation_log
WHERE reservation_id = R.id
AND change_type = 'cancel'
);