内部连接&外连接;表格的顺序是重要的吗?

时间:2008-10-09 13:00:55

标签: postgresql

为什么在组合外部和外部时表的顺序很重要内联? 以下是postgres的失败:

SELECT grp.number AS number,     
       tags.value AS tag   
FROM groups grp,
     insrel archiverel  
LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber   
LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber   
WHERE archiverel.snumber = 11128188 AND    
      archiverel.dnumber = grp.number 

结果:

ERROR:  invalid reference to FROM-clause entry for table "grp" LINE 5: LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.d... 
^ HINT:  There is an entry for table "grp", but it cannot be referenced from this part of the query.

当在FROM中反转组时,一切正常:

SELECT  grp.number AS number,     
        tags.value AS tag   
FROM    insrel archiverel,
        groups grp
LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber   
LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber   
WHERE   archiverel.snumber = 11128188 AND    
        archiverel.dnumber = grp.number 

5 个答案:

答案 0 :(得分:20)

我相信您可以将此视为运营商优先问题。

当你这样写:

FROM groups grp,
     insrel archiverel  
LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber   
LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber   

我认为它由解析器解释如下:

FROM groups grp,
(
  (
     insrel archiverel  
     LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber   
  )
LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber
)

如果是这样,那么在最里面的连接中,“grp”是未绑定的。

当你用“groups”和“insrel”反转这些行时,最里面的连接适用于“groups”和“ownrel”,所以它可以工作。

可能这也有效:

    FROM groups grp
         JOIN insrel archiverel  ON archiverel.dnumber = grp.number
    LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber   
    LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber 
WHERE archiverel.snumber = 11128188

答案 1 :(得分:18)

我认为没有人能够很好地解决这个问题,或者解释得非常好。你正在结合'旧式'(theta)和'新式'(ANSI)连接,我强烈怀疑这些连接是以你不期望的方式进行分组的。以这种方式看待它:

SELECT * FROM a, b JOIN c ON a.x = c.x

就像说

SELECT * FROM a, (b JOIN c on a.x = c.x)

其中括号内的东西代表一堆表合并到一个虚拟表中,并与'a'连接。显然'a'表不能成为连接的一部分,因为它只是稍后加入。扭转它,你正在做

SELECT * FROM b, (a JOIN c on a.x = c.x)

这是完全可以理解的,很好。我不确定为什么你没有使用ANSI连接语法,但这看起来有点奇怪(对于必须维护它的人来说是残忍的!)

答案 2 :(得分:5)

因为在第一个组中不是ON子句所属的连接的一部分。

答案 3 :(得分:4)

我不知道是什么导致了这种行为,如果它是一个错误或设计,但如果你坚持使用一种形式的连接或另一种形式,它应该可以正常工作。

SELECT grp.number AS number,     
       tags.value AS tag   
FROM groups grp
JOIN insrel archiverel ON archiverel.dnumber = grp.number
LEFT OUTER JOIN ownrel ownrel ON grp.number = ownrel.dnumber   
LEFT OUTER JOIN tags tags ON tags.number = ownrel.snumber   
WHERE archiverel.snumber = 11128188

如果行为是设计的,我很想知道更多。

答案 4 :(得分:2)

对于内部联接,表的顺序并不重要。

对于外部联接,它是。 所有指定一侧的表中的行(是LEFT还是RIGHT联接)将被包括在内,而只有符合连接条件的行将包含在另一侧的表中。< / p>

因为OUTER JOINS从一侧保留所有行,所以它们(通常)会增加结果集。 INNER JOINS只保留两边的行,如果它们匹配,那么它们(通常)会说减少结果集。因此,您通常希望在OUTER JOINS之前进行INNER JOINS(如果可能)。

在你的情况下,它几乎肯定是邪恶的A,B语法的结果。

相关问题