Mysql 使用左外部联接检查不存在相关行的最佳方法是什么

Mysql 使用左外部联接检查不存在相关行的最佳方法是什么,mysql,sql,join,outer-join,Mysql,Sql,Join,Outer Join,使用MySQL 5.x,我想有效地从表x中选择所有行,其中表Y中没有满足某些条件的相关行,例如 给出X中不存在与foo=bar相关的Y的所有记录 SELECT count(id) FROM X LEFT OUTER JOIN Y ON y.X_id = X.id AND y.foo = 'bar' WHERE y....? 据我所知,左外部联接保证为左第一个表中的每一行生成一行—在本例中为X—无论联接表中是否找到满意的行。我想做的是只选择那些找不到行的行 在我看来,如果没有匹配的记录,y.X_

使用MySQL 5.x,我想有效地从表x中选择所有行,其中表Y中没有满足某些条件的相关行,例如

给出X中不存在与foo=bar相关的Y的所有记录

SELECT count(id) FROM X
LEFT OUTER JOIN Y ON y.X_id = X.id AND y.foo = 'bar'
WHERE y....?
据我所知,左外部联接保证为左第一个表中的每一行生成一行—在本例中为X—无论联接表中是否找到满意的行。我想做的是只选择那些找不到行的行

在我看来,如果没有匹配的记录,y.X_id应该为NULL,但是这个测试似乎不起作用。y.X_id=0或!y、 X_id

编辑:更正了一些回复中指出的非的转录错误。修正了语法错误

SELECT count(id) FROM X 
LEFT OUTER JOIN Y ON (y.X_id = X.id AND y.foo = 'bar')
WHERE y.X_id is null
你很接近

首先按正常方式进行连接,然后选择Y中的NOTNULL行实际上为null的所有行,以便确保Y中不存在匹配项,而不仅仅是null值

还要注意您在查询中更正后的打字错误:

LEFT OUTER JOIN Y AS
-- should be
LEFT OUTER JOIN Y ON
-- This however is allowed
LEFT OUTER JOIN table2 as Y ON ....

检查表Y的主键是否为NULL将执行此操作,这表明联接不匹配:

SELECT count(id) FROM X 
LEFT OUTER JOIN Y ON (y.X_id = X.id AND y.foo = 'bar')
WHERE y.Y_id is null
为什么使用外部连接? 你就不能这样做:

SELECT count(id) 
FROM X JOIN Y AS y.X_id = X.id AND y.foo <> 'bar'

约翰的答案是100%正确的

除此之外,还有以下选项:

SELECT count(id)
FROM X 
WHERE NOT EXISTS
  ( SELECT * 
    FROM Y
    WHERE (y.X_id = X.id AND y.foo = 'bar')
  )
根据您的表大小和数据分布,这可能更有效。测试并保留这两种方法以备将来参考。

您必须记住NULL是特殊值!这就是为什么我在mysql文档中有一章叫做4.3.4.6处理空值

链接:


享受吧

这将选择匹配项,OP将查找不匹配项。它将为他提供从X开始的所有行,其中Y中有一个匹配行,该行没有Y.foo=bar,请注意。我可能误解了这个问题…内部连接永远不会给出不匹配的行,它只会将这些行隐藏在视图中,这就是问题所在。注意,对于y.X_id=X.id和y.foo='bar',外部连接测试是如何进行的,与之完全相反的是y.X_id X.id或y.foo'bar',但这将导致不同的结果,每个X行有许多匹配的y行。我确实误解了这个问题。。我的坏人:这是一个很常见的错误。SQL使用的三元逻辑有时甚至让有经验的SQL开发人员感到困惑。您可以在MySQL中使用NULL:-您能详细说明什么时候不存在更有效吗?也许当表X很大而表Y很小时?只是好奇,谢谢。左JOIN/NOT NULL解决方案和NOT EXISTS解决方案可能会导致与execution planner不同的计划。这可能取决于很多因素,如使用mySQL或SQL Server或其他数据库系统、系统版本、特定引擎InnoDB或MyISAM、表的大小、连接字段的分布(如Y上实际存在的X.id的百分比)、字段中是否有空值等等,我对这个复杂的依赖性有一个非常奇妙的演示,这个空白太窄了,无法包含。你可以阅读这个问题,其中有很多关于这个问题的讨论,还有很多关于外部材料的链接。所以:底线是,不同的计划将导致执行时间略有不同或非常不同。在您的计算机中使用数据进行测试,使用各种表格大小和设置,在您的情况下使用最好的。如果有迹象表明查询速度较慢。如果它运行得足够快,就不需要花时间进行优化。我只是在用JOIN解决方案砸了头之后才尝试了NOT EXISTS,但它在我脸上爆炸了,我非常小心。至少在我的经验中,我发现任何涉及子查询的操作都比仔细连接的性能要差得多。但我正在与MySQL5合作,所以当然是YMMV。然后,这个Oracle的家伙再次建议将子查询重写为连接以提高性能:谢谢。正如我在编辑中提到的,这是一个失误。当然,实际的查询是一团乱麻,所以我试图简化。没有帮助,特别是因为链接的文章没有任何有用的信息,对这个问题有帮助的答案很久以前就已经发布了。