为什么在组合外部和外部时表的顺序很重要内联? 以下是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
答案 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语法的结果。