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

发布于 2024-08-24 15:06:47 字数 1111 浏览 6 评论 0原文

我陷入了一个带有连接的查询。客户端站点运行的是 mysql4,因此不能选择子查询。我尝试使用联接重写的效果不太好。

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

表:承包商

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

表:contractors2label

身份证号
标签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

I'm stuck on a query with a join. The client's site is running mysql4, so a subquery isn't an option. My attempts to rewrite using a join aren't going too well.

I need to select all of the contractors listed in the contractors table who are not in the contractors2label table with a given label ID & county ID. Yet, they might be listed in
contractors2label with other label and county IDs.

Table: contractors

cID (primary, autonumber)
company (varchar)
...etc...

Table: contractors2label

cID
labelID
countyID
psID

This query with a subquery works:

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
   )

I thought this query with a join would be the equivalent, but it returns no results. A manual scan of the data shows I should get 34 rows, which is what the subquery above returns.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

稀香 2024-08-31 15:06:47

进行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

顺便说一句:使用别名(如我的示例中的 c)可以使读取和编写查询变得更容易。

When doing a LEFT JOIN, you need to put all conditions of the JOIN into the ON clause.

In your example you get NULL for left joined columns that do not exist, but you then compare them to values again (<> 1) which does not work.

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: Using aliases (like c in my example) makes reading and writing your queries easier.

无敌元气妹 2024-08-31 15:06:47

当您使用 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

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

When you restrict on a where clause using the columns in a table that's LEFT joined, you are effectively removing the LEFT OUTER part of the join, because you're filtering on columns that have to be there. Try this instead:

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

This does the restriction as part of the join, so nulls can still be used in the larger query.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文