2左表连接2个表?

时间:2011-02-20 22:11:13

标签: sql mysql

我在MySQL:

我有2个表,一个是主表,另一个是附件表,其中包含一些支持主表记录的信息。

示例:

表门户网站:

id title desc
12  "aaa" "desc"
13  "bbb" "desc"
[etc]

辅助表(省略主要id字段)

type portalid
 x    12
 2    12
 3    12
 4    12
 5    12

 1    13
 2    13
 4    13

我需要选择表门户中的每条记录,这些记录在次表中获得了类型= 4但是!= 5的记录。

示例:

SELECT * 
  FROM portal,secondary_table s
 WHERE portal.id=s.portalid 
   AND type of secondary_table is 4 and is not 5

结果:

在这种情况下,只返回门户网站的记录13,因为记录12同时包含类型4和5。

请注意我问了一个类似的问题,但只考虑了一个表格,并且该查询需要花费超过50秒才能详细说明。

感谢您的帮助

3 个答案:

答案 0 :(得分:2)

您应该考虑使用NOT EXISTS条款对其进行重新措辞。如果您想要的只是来自portal的记录,那么双EXISTS子句将起作用并且非常清楚地显示查询意图

SELECT * 
FROM portal
WHERE EXISTS (select * from secondary_table s1
              where portal.id=s1.portalid
              and s1.type=4)
AND NOT EXISTS (select * from secondary_table s2
                where portal.id=s2.portalid
                and s2.type=5)

但是,由于MySQL处理EXISTS子句的方式(即使它更清楚),您可以使用LEFT JOIN / IS NULL来权衡澄清性能。请阅读以下链接,但每个查询的性能可能因特定数据分布而异,因此请尝试使用两者并使用更适合您数据的方式。

NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL: MySQL

将写入LEFT JOIN / IS NULL表单

SELECT * 
FROM portal
JOIN secondary_table s1 ON portal.id=s1.portalid and s1.type=4
LEFT JOIN secondary_table s2 ON portal.id=s2.portalid and s2.type=5
WHERE s2.portalid IS NULL

表(portal,inner,left)的顺序是允许处理前两个表(portal + secondary / type = 4)并在启动到LEFT(外部)JOIN之前提前修剪结果集(保留对于存在性测试,从左侧开始的一切。

答案 1 :(得分:1)

这就是为什么你应该避免旧的FROM A,B语法 - 它在某些方面不那么强大。使用显式连接类型(LEFT / RIGHT / INNER / FULL / CROSS)。

SELECT <columns>
FROM portal p
LEFT JOIN secondary s1 ON p.id=s1.portalid AND s1.type = 5
INNER JOIN secondary s2 ON p.id=s2.portalid AND s2.type = 4
WHERE s1.type IS NULL 

答案 2 :(得分:0)

我将使用与richard的EXISTS非常相似的查询:

SELECT * FROM portal 
WHERE id IN (SELECT portalid FROM sec WHERE type=4) 
      AND id NOT IN (SELECT portalid FROM sec WHERE type=5)

imo它更具可读性。