右表中空结果的内连接
Posted
技术标签:
【中文标题】右表中空结果的内连接【英文标题】:inner join with empty result from right table 【发布时间】:2013-08-08 21:06:31 【问题描述】:我有2张桌子,餐厅和订单,每个餐厅可以有很多订单
restaurants table
id
name
orders table
id
restaurant_id
date
我需要找到在某个日期范围内没有订单的餐厅。在订单表中,我将订单日期保存为 - 每行代表一天。所以,我需要进行内部连接,但订单表没有结果。比如说,我需要找到在2013-08-09 to 2013-08-11
日期范围内免费的餐厅。我怎样才能做到这一点?如何根据日期范围查询订单表中没有匹配项的餐厅?
实际上,我可以将状态为 not_ordered 的订单表中的所有日期保存起来,并使用not_ordered = true
条件进行内部连接,但在这种情况下,我必须使用日期填充所有表,这不是对我来说是件好事。
谢谢
【问题讨论】:
看看here also,类似的问题,但joins
没有重音
【参考方案1】:
select r.*
from restaurant r
left join orders o on r.id = o.restaurant_id and o.date between '...' and '...'
where o.id is null;
或者您可以使用not exists
来完成,如其他答案所示。
【讨论】:
+1。这是经典的“反连接”模式:一个 LEFT JOIN 来查找匹配的行(所有餐厅以及匹配的订单),然后是一个 WHERE 子句来消除在订单中具有匹配行的餐厅。这通常比使用NOT IN
或 NOT EXISTS
谓词的等效查询。【参考方案2】:
您不想为此使用内部联接。您可以使用外连接,或使用NOT EXISTS
和子查询。
这是后一种方法的一个示例:
select r.id,r.name
from restaurants r
where not exists (
select NULL
from orders o
where o.restaurant_id = r.id
and o.date >= '2013-08-09'
and o.date <= '2013-08-11'
);
【讨论】:
+1。相关子查询引用了外部查询中的表达式。这就是它的完成方式,尽管我们通常(并非总是)通过反连接获得更好的性能。 我自己更经常使用反连接,但我认为了解这两种方法很有用。 我同意了解这两种方法很有用,这就是为什么我赞成您的回答。有时NOT EXISTS
谓词是更合适的方法。【参考方案3】:
我不是很了解mysql,但这应该可以作为通用SQL:
SELECT *
FROM restaurants
WHERE NOT EXISTS(SELECT 1
FROM order
WHERE restaurant_id=id AND
date BETWEEN '2013-08-09' AND '2013-08-11')
【讨论】:
子查询中的id
是对restaurant
表或order
表中的id
列的引用吗?最佳实践要求列引用必须使用表名或最好使用表别名来限定。以上是关于右表中空结果的内连接的主要内容,如果未能解决你的问题,请参考以下文章