仅在值不存在时返回行

问题描述 投票:4回答:2

我有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在这里不起作用。

mysql sql
2个回答
12
投票
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测试匹配这些行,因此它找到表之间没有匹配的所有行。


3
投票

只是为了完整(我真的相信它更适合),我鼓励你使用一个简单的NOT EXISTS

SELECT * FROM reservation R
WHERE NOT EXISTS (
  SELECT 1 FROM reservation_log
  WHERE reservation_id = R.id
    AND change_type = 'cancel'
);
© www.soinside.com 2019 - 2024. All rights reserved.