帮助将子查询转换为带连接的查询

时间:2010-03-13 12:53:21

标签: sql mysql left-join

我坚持使用连接查询。客户端的站点正在运行mysql4,因此子查询不是一个选项。我尝试使用连接重写的尝试并不顺利。

我需要选择承包商表中列出的所有承包商,这些承包商不在承包商2标签表中,并且具有给定的标签ID&县ID。然而,他们可能会被列入 承包商2标签与其他标签和县ID。

表:承包商

  

cID(主要,自动编号)
  公司(varchar)
  ...等等...

表:承包商2标签

  

CID
  labelID
  countyID
  psID

带子查询的查询有效:

SELECT company, contractors.cID
   FROM contractors
   WHERE contractors.complete = 1
   AND contractors.archived = 0
   AND contractors.cID NOT IN (
     SELECT contractors2label.cID FROM contractors2label
        WHERE labelID <> 1 AND countyID <> 1
   )

我认为这个带有连接的查询是等价的,但它不返回任何结果。手动扫描数据显示我应该得到34行,这就是上面的子查询返回的内容。

SELECT company, contractors.cID
   FROM contractors 
   LEFT OUTER JOIN contractors2label ON contractors.cID = contractors2label.cID
   WHERE contractors.complete = 1
   AND contractors.archived = 0
   AND contractors2label.labelID <> 1
   AND contractors2label.countyID <> 1
   AND contractors2label.cID IS NULL

2 个答案:

答案 0 :(得分:2)

执行LEFT JOIN时,您需要将JOIN的所有条件都放入ON子句中。

在您的示例中,对于不存在的左连接列,您会获得NULL,但您可以将它们再次与值(<> 1)进行比较,但这些值不起作用。

SELECT c.company, c.cID
   FROM contractors c
   LEFT JOIN contractors2label c2
          ON ( c2.cID = c.cID AND c2.labelID <> 1 AND c2.countyID <> 1 )
   WHERE c.complete = 1
   AND c.archived = 0
   AND c2.cID IS NULL

BTW:使用别名(例如我的示例中的c)可以更轻松地阅读和编写查询。

答案 1 :(得分:2)

当您使用LEFT加入的表中的列限制where子句时,您实际上正在删除联接的LEFT OUTER部分,因为您要过滤必须包含的列那里。试试这个:

SELECT company, contractors.cID
   FROM contractors 
   LEFT OUTER JOIN contractors2label 
       ON (contractors.cID = contractors2label.cID
           AND contractors2label.labelID <> 1
           AND contractors2label.countyID <> 1)
   WHERE contractors.complete = 1
   AND contractors.archived = 0
   AND contractors2label.cID IS NULL

这将限制作为连接的一部分,因此仍可以在较大的查询中使用null。