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

时间:2013-01-10 15:03:32

标签: 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'

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

我该如何做到这一点?

3 个答案:

答案 0 :(得分:35)

这种查询应该有效 - 在用显式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'

此处的跳闸线是明确的JOIN在“旧式”CROSS JOIN之前以逗号( , )绑定。 I quote the manual here:

  

在任何情况下JOIN都比逗号分隔更紧密   FROM - 列出项目。

在重写第一个之后,所有连接都是从左到右应用的(逻辑上 - 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'

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

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

答案 1 :(得分:4)

你可以这样做

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'

答案 2 :(得分:2)

JOIN语句也是FROM子句的一部分,更正式地说, join_type 用于将两个 from_item 组合成一个 from_item ,其中多个可以在FROM之后形成以逗号分隔的列表。请参阅http://www.postgresql.org/docs/9.1/static/sql-select.html

因此,您问题的直接解决方案是:

SELECT something
FROM
    master as parent LEFT JOIN second as parentdata
        ON parent.secondary_id = parentdata.id,
    master as child LEFT JOIN second as childdata
        ON child.secondary_id = childdata.id
WHERE parent.id = child.parent_id AND parent.parent_id = 'rootID'

更好的选择是仅使用JOIN,因为它已被建议。