有人可以解释为什么这个左外连接的行为是这样的吗?

时间:2014-01-29 14:34:38

标签: mysql join left-join

我有两个表itemitem_popularity,并且需要找到一些作为输入提供的项目,这些表格没有受欢迎程度。我认为LEFT OUTER JOIN之后进行NULL检查会是正确的方法,但我一直都有一些非常奇怪的行为。然后我稍微修改了一下查询并让它工作,但我真的很想理解为什么它会这样表现。

我们假设这些表具有以下值:

 item
+----+----------+
| id | name     |
+----+----------+
| 1  | Item 1   |
| 2  | Item 2   |
| 3  | Item 3   |
| 4  | Item 4   |
| 5  | Item 5   |
+----+----------+

item_popularity
+---------+-------------+----------+
| id_item | popularity  | id_store |
+---------+-------------+----------+
| 1       | 0.78        | 1        |
| 3       | 0.23        | 1        |
| 4       | 0.6765      | 1        |
+----+------------------+----------+

我的原始查询如下:

SELECT item.id, item.name, item_popularity.popularity FROM item
LEFT OUTER JOIN item_popularity
ON item.id = item_popularity.id_item
WHERE item.id IN (provided input)
AND id_store = (provided store)
AND item_popularity.id_item IS NULL

然而,这将不会返回任何项目,因为它只会加入HAD受欢迎的项目,可以看到on this fiddle。我google了一下,发现很多人有同样的问题,到处都有人说要将WHERE子句的第一位移到JOIN,因为它的方式会导致{ {1}}成为LEFT JOIN或类似的东西。

所以我这样做了,然后查询变成了:

INNER JOIN

现在到了奇怪的位置。假设我正在寻找第2,3和5项。我知道只有3个有人气得分,所以我应该看到2和5作为结果,对吧?好吧,有点。我在那里看到2和5,但它也在结果中列出了1和4! Here's the fiddle

好的,所以我设法获得正确结果的唯一方法是重复SELECT item.id, item.name, item_popularity.popularity FROM item LEFT OUTER JOIN item_popularity ON item.id = item_popularity.id_item AND item.id IN (provided input) AND id_store = (provided store) WHERE item_popularity.id_item IS NULL 子句中的id过滤器,使查询看起来很丑陋,如here所示:

WHERE

我不知道是否应该重复SELECT item.id, item.name, item_popularity.popularity FROM item LEFT OUTER JOIN item_popularity ON item.id = item_popularity.id_item AND item.id IN (provided input) AND id_store = (provided store) WHERE item.id IN (provided input) AND item_popularity.id_item IS NULL 中的id_store过滤器,我可能只是为了确定。任何人都可以解释为什么会发生这种情况并且有更好的方法来解决它吗?

2 个答案:

答案 0 :(得分:0)

您的第一个查询不起作用的原因不是因为LEFT表上的条件,而是因为您在RIGHT表上有条件。在你的小提琴中完全删除WHERE子句,但选择你将要使用的所有字段(只是将它们视为调试练习)。所以,使用:

SELECT item.id, item.name, item_popularity.popularity, id_store 
FROM item
LEFT OUTER JOIN item_popularity
ON item.id = item_popularity.id_item

执行此操作后,您将看到条件item_popularity.id_store = 1将排除您认为被排除的记录。

答案 1 :(得分:0)

select item.id, item.name, item_popularity.popularity
from item 
left join item_popularity 
on item.id = item_popularity.id_item
where item_popularity.popularity is null

您获取完整的项目表,将其存在的流行度表添加到它,并在不存在的地方添加空值。然后检查流行度具有空值的位置(您还可以检查item_popularity.id_item,因为它将在给定数据的相同行上具有空值)。