为什么在组合外部和内部连接时表的顺序很重要?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
Dave Costa.. 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
Cowan.. 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"连接的theta-join.显然'a'表不能成为连接的一部分,因为它只是稍后加入.扭转它,你正在做
SELECT * FROM b, (a JOIN c on a.x = c.x)
这是完全可以理解的,很好.我不确定为什么你没有使用ANSI连接语法,但这似乎有点奇怪(对于必须维护它的人来说是残忍的!)
我相信您可以将此视为运营商优先级问题.
当你写这个:
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
我认为没有人能够很好地解决这个问题,或者解释得非常好.你正在结合'旧式'(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"连接的theta-join.显然'a'表不能成为连接的一部分,因为它只是稍后加入.扭转它,你正在做
SELECT * FROM b, (a JOIN c on a.x = c.x)
这是完全可以理解的,很好.我不确定为什么你没有使用ANSI连接语法,但这似乎有点奇怪(对于必须维护它的人来说是残忍的!)
因为在第一个grp不是ON子句所属的连接的一部分.