为什么这两个查询会产生不同的结果?
此查询提供所有记录,而不管已删除列的值如何。它好像忽略了这个选择:
SELECT mcm.record_id, mc.category, mc.category_id, mc.deleted, mcm.member_id
FROM mailing_category mc
LEFT OUTER JOIN mailing_category_membership mcm
ON mc.category_id = mcm.category_id
AND mcm.member_id = 6346
AND mc.deleted = 'false'
WHERE mcm.record_id IS NULL
此查询仅选择已删除列为false的记录,这就是我想要的。
SELECT mcm.record_id, mc.category, mc.category_id, mc.deleted, mcm.member_id
FROM mailing_category mc
LEFT OUTER JOIN mailing_category_membership mcm
ON mc.category_id = mcm.category_id
AND mcm.member_id = 6346
WHERE mcm.record_id IS NULL
AND mc.deleted = 'false'
为什么这两个查询会给出不同的结果?我使用的是MySQL 5.5.37版。
答案 0 :(得分:2)
left outer join
的逻辑是从第一个表中获取所有记录。如果第二个表中有一个或多个匹配项,则在结果集中包含这些匹配项。如果没有匹配项,则仍然在结果集中包含原始记录,其他所有列都为NULL。匹配意味着on
子句的计算结果为true。
这适用于第一个表上的过滤。所以在这个表达式中:
FROM mailing_category mc LEFT OUTER JOIN
mailing_category_membership mcm
ON mc.category_id = mcm.category_id AND mcm.member_id = 6346 AND
mc.deleted = 'false'
您认为您正在mc.deleted = 'false'
上过滤。但是,这只是意味着没有匹配(因为on
子句的计算结果为false)。记录仍然保留,因为这是left outer join
的逻辑。
当您将mc
上的条件移动到where
子句时,过滤会按预期进行。
答案 1 :(得分:1)
因为在执行OUTER JOIN时,在查询处理期间的不同时间进行过滤
对OUTER JOIN的结果执行WHERE子句。
对OUTER JOIN的输入执行ON子句。
INNER JOIN也是如此;但在这种情况下,不同的处理时间仍然是相同的结果。
答案 2 :(得分:1)
就好像忽略了这个选择:
因为您正在使用外部联接。
左外连接意味着返回第一个表中的所有行,如果第二个表中的行与连接条件匹配,则将它们排成同一行。然后应用WHERE子句。如果它们不匹配,您仍会得到一行,只有第二个表的NULL
值。
换句话说,outer join
永远不会取消返回行的资格。当然,WHERE
条款与inner join
一样。
您可能会问,如果连接条件没有取消对行的限制,那么连接条件对外连接有什么影响?很简单,它们为右边的给定行指定它是否应该与左边的行对齐。
所以你认为过滤器没有被应用。事实上,它应用于从第二个表中选择行以与第一个行一起使用。
答案 3 :(得分:0)
使用左连接,将返回表mailing_category
中的所有记录(然后由WHERE
查询过滤),无论连接是否在mailing_category_membership
中找到任何行,如果连接不成功,mailing_category_membership
中的每一列都将为NULL。因此,在第一个查询中,您的WHERE
也将返回mailing_category
中未找到匹配匹配项的每一行。