Mysql 仅当值不存在时返回行

Mysql 仅当值不存在时返回行,mysql,sql,Mysql,Sql,我有两张桌子-预订: 第二个表-预订日志: 我只需要选择未取消的预订,在本例中它仅为ID 3。 我可以用一个简单的WHERE change\u type=cancel条件轻松地选择cancelled,但我很难选择NOT cancelled,因为简单的WHERE在这里不起作用 SELECT * FROM reservation WHERE id NOT IN (select reservation_id FROM reservation_log

我有两张桌子-预订:

第二个表-预订日志:

我只需要选择未取消的预订,在本例中它仅为ID 3。 我可以用一个简单的WHERE change\u type=cancel条件轻松地选择cancelled,但我很难选择NOT cancelled,因为简单的WHERE在这里不起作用

SELECT *
FROM reservation
WHERE id NOT IN (select reservation_id
                 FROM reservation_log
                 WHERE change_type = 'cancel')
或:

第一个版本更直观,但我认为第二个版本通常会获得更好的性能,前提是在联接中使用的列上有索引


第二个版本可以工作,因为LEFT JOIN为第一个表中的所有行返回一行。当ON条件成功时,这些行将包括第二个表中的列,就像内部联接一样。当条件失败时,返回的行将包含第二个表中所有列的NULL。WHERE l.id IS NULL测试然后匹配这些行,因此它会查找表之间不匹配的所有行。

为了完整性,我相信它更适合,我鼓励您使用简单的NOT EXISTS


请参阅不相等文档:这些注释不正确,因为1和2具有类型!=取消。如果我在更改类型时使用不相等条件!='cancel“它打印所有预订,这是错误的,因为只有id为3的预订未被取消。如果您正在比较的数据可能为空,请务必小心使用not IN。例如,请参阅@Barmar Well,因为您似乎希望我在这个问题上而不是我自己的问题上寻求帮助。。。。当从子查询调用多个列时,我如何做到这一点?请记住,内部联接需要一个匹配的列,该列将始终删除不匹配的结果,这在我的情况下不起作用,因为我需要两个都包含用户名的列。@Bruce您可以在t2.blocker中的t1.username上使用,t2.加入时阻止匹配任一列。我不需要匹配任何一列,我需要匹配两列。如果我匹配其中一个,它将不会返回另一个的结果。然后使用ON t1.username=t2.blocker和t1.username=t2.blocked来匹配这两个。这是基本的SQL。@Bruce尝试理解它的逻辑,而不仅仅是复制代码。如果您了解它是如何工作的,您将能够概括到许多不同的情况。
   id  | reservation_id | change_type
   ----+----------------+-------------
   1   | 1              | create
   2   | 2              | create
   3   | 3              | create
   4   | 1              | cancel
   5   | 2              | cancel
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
SELECT * FROM reservation R
WHERE NOT EXISTS (
  SELECT 1 FROM reservation_log
  WHERE reservation_id = R.id
    AND change_type = 'cancel'
);