仅当值不存在时才返回行
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'
);
【讨论】:
以上是关于仅当值不存在时才返回行的主要内容,如果未能解决你的问题,请参考以下文章