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

Posted

技术标签:

【中文标题】帮助将子查询转换为带连接的查询【英文标题】:Help converting subquery to query with joins 【发布时间】:2010-03-13 12:53:20 【问题描述】:

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

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

表:承包商

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

表:contractors2label

cID 标签ID 县ID 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

【问题讨论】:

+1 表示是新手,并设法提供格式正确的问题,并很好地描述了您的问题,包括示例代码 :) 【参考方案1】:

在做LEFT JOIN时,需要将JOIN的所有条件放入ON子句中。

在您的示例中,您会为不存在的左连接列获得 NULL,但您随后将它们再次与无效的值 (&lt;&gt; 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

顺便说一句:使用别名(例如我的示例中的 c)可以让您更轻松地阅读和编写查询。

【讨论】:

好吧,我不应该跳得这么快。当我将它插入我的应用程序时,它实际上不起作用。 @Tim:你能描述一下你面临的问题吗? 我的错……我的逻辑是落后的。如果我更改为 ON ( c2.cID = c.cID AND c2.labelID = 1 AND c2.countyID = 1 ),您的查询将为我提供我需要的东西,顺便说一句,我认为下面@Nick 的答案也可以使用 to = 改变。 @Tim:我同意,尼克斯的回答也应该有效。我认为你应该投票 - 如果你愿意,你也可以投票给我的 ;-) 我刚刚在这里创建了一个帐户,以便对答案进行投票。谢谢你们!【参考方案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

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

【讨论】:

以上是关于帮助将子查询转换为带连接的查询的主要内容,如果未能解决你的问题,请参考以下文章

将子查询转换为单个查询 Hive

将子查询转换为 JSON 性能

将子选择 sql 查询转换为 laravel 查询

mysql 将子查询排除在连接之外

Laravel 6,MYSQL - 如何使用 Laravel Querybuilder 或 Model Eloquent 将子查询与 GroupBY 左连接?

postgres 将子字符串转换为纪元