在检查一个表的pk =其他表的fk时,所有类型的连接是否都会减少为内连接?

时间:2009-06-10 13:12:23

标签: sql

无论您使用哪种类型的连接,如果您的WHERE子句检查一个表的pk =其他表的fk,它是否正确,只要结果集是conncerned,它就变得与内连接相同?换句话说,如果您的SQL查询包含以下内容:

“选择...从A左边加入B开(...)E,F全外加入G开(A.pk = G.fk)...... WHERE A.pk = G.fk和A. pk = B.fk等......“

在上面的查询中,A左边连接到B,而G在其fk上外连接到A.但由于where子句有两个检查,所以整个查询简化为:

“选择...从A INNER JOIN B开(...)E,F INNER加入G(A.pk = G.fk)...等等......” ?

询问此查询的原因是我有许多笛卡尔类型连接以及一个表的pk =其他表的fk中的where子句,这会减慢查询速度。我想用左连接替换笛卡尔积,并保留所有where子句或所有内连接。

3 个答案:

答案 0 :(得分:3)

是的,这是获得内部联接的迂回方式。

想想它是如何工作的:它从A中拉出所有内容,然后是匹配的B或空,然后是所有G(A / B和G侧的空值),然后它基本上过滤掉了所有具有空值的东西它(WHERE子句)。所以,是的,INNER JOIN可能更快。

这种混淆的一个常见原因是:

SELECT * FROM a INNER JOIN b ON a.id = b.id AND b.something = 'awesome'

相当于:

SELECT * FROM a INNER JOIN b ON a.id = b.id WHERE b.something = 'awesome'

但是,这种相同的传递方法不适用于完整/外连接,因为它将进行连接然后过滤(当然,取决于过滤器和优化器)。

因此,简而言之:如果你真的想要一个内部联接,请使用内部联接。

编辑:我还应该注意,这不是PK / FK协议,如果你在WHERE子句中重复你的ON子句,那么完整/外连接将等同于内部连接。

答案 1 :(得分:1)

是的,你也可以简单地添加

"Where PK Is Not Null" or 
"Where FK Is Not Null" 

这也会从联接的“外部”一侧过滤出“额外”记录......

答案 2 :(得分:1)

如果您在where子句中引用左外连接的右侧除了“myfield为null”之外的任何内容,则表示已创建内连接。这是因为它筛选出任何不符合该条件的内容,包括与初始表不匹配的所有记录。与其他非内连接相同。为了解决它,你把条件放在连接中。示例(这将其转换为内部联接):

Select field1, field2 from mytable mt
left join mytable2 mt2 on mt.id = m2.id
where mt1.field1 = 'hello' and mt2.field2 = 'test'

重写以保留左连接:

Select field1, field2 from mytable mt
left join mytable2 mt2 on mt.id = m2.id and mt2.field2 = 'test'
where mt1.field1 = 'hello' 

我还想评论一下您在评论中所说的内容,但我认为我的回复对于其他评论来说太长了。

“从内部连接B选择...(A.id = B.a_id),C,D,F,其中A.id = F.id” to:“选择...从内部加入B开始(A.id = B.a_id),C,D INNER加入F on A.id = F.a_id”

您不希望合并这样的语法;这变得非常难以维护。事实上,我建议不要使用旧式逗号语法,因为它会受到意外交叉连接的影响。因此,在您的示例中,我会编写以获取您当前获得的结果集(至少有人维护将知道您的交叉连接而不是意外地执行):

Select ... From A 
INNER JOIN B on A.id = B.a_id 
INNER JOIN F on A.id = F.a_id
CROSS JOIN C
CROSS JOIN D

如果交叉连接是偶然的,代码将改为:

Select ... From A 
INNER JOIN B on A.id = B.a_id
INNER JOIN F on A.id = F.a_id
INNER JOIN C on (fill in the join fields)
INNER JOIN D on (fill in the join fields)