我有两张桌子 - 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
在这里不起作用。
答案 0 :(得分:12)
SELECT *
FROM reservation
WHERE id NOT IN (select reservation_id
FROM reservation_log
WHERE change_type = 'cancel')
OR:
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
测试匹配这些行,因此它会找到表之间没有匹配的所有行。
答案 1 :(得分:3)
为了完整(我真的相信它更合适),我建议你使用一个简单的NOT EXISTS
。
SELECT * FROM reservation R
WHERE NOT EXISTS (
SELECT 1 FROM reservation_log
WHERE reservation_id = R.id
AND change_type = 'cancel'
);