我有一个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子句中的第一个表,第二个连接将永远不会像这样工作。
我该如何做到这一点?
答案 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
,因为它已被建议。