仅当值不存在时才返回行

Posted

技术标签:

【中文标题】仅当值不存在时才返回行【英文标题】:Return row only if value doesn't exist 【发布时间】:2014-03-05 04:21:34 【问题描述】:

我有 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 条件轻松选择取消,但我正在努力解决未取消的问题,因为简单的WHERE 在这里不起作用。

【问题讨论】:

参考不等文档:dev.mysql.com/doc/refman/5.0/en/… 那些 cmets 不正确,因为 1 和 2 的类型为 != cancel。 如果我使用不相等条件 WHERE change_type != 'cancel' 它会打印所有预订,这是错误的,因为只有 id 为 3 的预订不会被取消 如果您要比较的数据可能为 NULL,请务必小心使用 NOT IN (),例如见***.com/a/129152/2067753 【参考方案1】:
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 测试会匹配这些行,因此它会找到所有表之间不匹配的行。

【讨论】:

@Barmar 好吧,因为您似乎希望我在这个问题上而不是我自己的问题上寻求帮助....从子查询中调用多个列时我该怎么做,记住内部连接需要一个匹配的列,它总是会删除不匹配的结果,这在我的情况下不起作用,因为我需要两列都包含用户名。 @Bruce 您可以在加入时使用ON t1.username in (t2.blocker, t2.blocked) 匹配任一列。 我也不需要匹配,我需要两个都匹配。如果我匹配一个,它不会返回另一个的结果。 然后使用ON t1.username = t2.blocker AND t1.username = t2.blocked 来匹配两者。这是基本的 SQL。 @Bruce 尝试理解它的逻辑,而不仅仅是复制代码。如果您了解它的工作原理,您将能够推广到许多不同的情况。【参考方案2】:

为了完整起见(老实说,我相信它更合适),我鼓励您使用简单的NOT EXISTS

SELECT * FROM reservation R
WHERE NOT EXISTS (
  SELECT 1 FROM reservation_log
  WHERE reservation_id = R.id
    AND change_type = 'cancel'
);

【讨论】:

以上是关于仅当值不存在时才返回行的主要内容,如果未能解决你的问题,请参考以下文章

sql Oracle:仅当值存在时才从另一个表中插入值

仅当值不存在时才使用lodash push到数组?

仅当行不存在时才插入 SQL

仅当行不存在时才附加到 csv

MYSQL - 仅当 LEFT JOIN 中的行不存在时才选择

Spring - 仅当值不为空时才设置属性