一个查询中多个表上的多个左连接

Den*_*der 24 sql postgresql join left-join multiple-tables

我有一个master表,其中有多个级别存储的项目,父项和子项,还有第二个表可能有也可能没有其他数据.我需要从我的主表中查询两个级别,并在我的第二个表上有一个左连接,但由于我的查询中的排序,这将不起作用.

SELECT something FROM master as parent, master as child
  LEFT JOIN second as parentdata ON parent.secondary_id = parentdata.id
  LEFT JOIN second as childdata ON child.secondary_id = childdata.id
WHERE parent.id = child.parent_id AND parent.parent_id = 'rootID'
Run Code Online (Sandbox Code Playgroud)

左连接仅适用于from子句中的最后一个表,因此我只能使其适用于其中一个左连接.在上面的示例中,左连接都不起作用,因为第一个左连接指向from子句中的第一个表,第二个连接将永远不会像这样工作.

我怎样才能做到这一点?

Erw*_*ter 41

在使用显式ANSI JOIN语法重写之后,这种查询应该有效:

SELECT something
FROM   master      parent
JOIN   master      child ON child.parent_id = parent.id
LEFT   JOIN second parentdata ON parentdata.id = parent.secondary_id
LEFT   JOIN second childdata ON childdata.id = child.secondary_id
WHERE  parent.parent_id = 'rootID'
Run Code Online (Sandbox Code Playgroud)

这里的跳闸线是JOIN在"旧式"之前CROSS JOIN使用逗号(,)明确绑定.我在这里引用手册:

在任何情况下,JOIN绑定比逗号分隔FROM-list项更紧密 .

在重写第一个之后,所有连接都是从左到右应用的(逻辑上 - Postgres可以自由重新排列查询计划中的表),并且它可以正常工作.

只是为了表明我的观点,这也可行:

SELECT something
FROM   master parent
LEFT   JOIN second parentdata ON parentdata.id = parent.secondary_id
,      master child
LEFT   JOIN second childdata ON childdata.id = child.secondary_id
WHERE  child.parent_id = parent.id
AND    parent.parent_id = 'rootID'
Run Code Online (Sandbox Code Playgroud)

但是显式JOIN语法通常更可取,正如您的案例再次说明的那样.

并注意多个(LEFT)JOIN可以乘以行:


pra*_*ala 5

你可以这样做

SELECT something
FROM
    (a LEFT JOIN b ON a.a_id = b.b_id) LEFT JOIN c on a.a_aid = c.c_id
WHERE a.parent_id = 'rootID'
Run Code Online (Sandbox Code Playgroud)

  • @DeniseMeander:我不知道为什么接受这个答案.它没有为旧问题添加任何新内容 - 除了括号外,在这种情况下只是噪音.也没有解释.默认情况下,显式连接从左到右执行(除非连接条件强制使用不同的顺序). (4认同)