MySQL:用两个 table 表示完全连接,它们具有到公共基础 table 的外键
MySQL: Expressing full joins with two tables having foreign keys to a common base table
假设我们需要对表 1-3 执行两次 FULL JOIN
查询(在 PostgreSQL 术语中),其中表 2 和表 3 都有指向表 1 的外键。这将适用于 MySQL,其中 FULL JOIN
不可用。因此必须找到解决方法。
从 LEFT JOIN
s 开始,以下代码按照 (1) 中的描述工作:
SELECT table1.ID, table1.x, table2.y, table3.z
FROM (table1
LEFT JOIN table2
ON table1.ID = table2.FOREIGN_ID)
LEFT JOIN table3
ON table1.ID = table3.FOREIGN_ID
在 (2) 之后,我能够使用 UNION
语句为单个连接模拟完整的外部连接:
SELECT table1.ID, table1.x, table2.y
FROM table1
LEFT JOIN table2
ON table1.ID = table2.FOREIGN_ID
UNION
SELECT table1.ID, table1.x, table2.y
FROM table1
RIGHT JOIN table2
ON table1.ID = table2.FOREIGN_ID
屈服
和
SELECT table1.ID, table1.x, table3.z
FROM table1
LEFT JOIN table3
ON table1.ID = table3.FOREIGN_ID
UNION
SELECT table1.ID, table1.x, table3.z
FROM table1
RIGHT JOIN table3
ON table1.ID = table3.FOREIGN_ID
ORDER BY ID
屈服
我需要有关如何从此处获取此输出的建议:
也就是说,通过外键引用表 1 中的条目的结果行应该正确连接,而表 2 和表 3 中的杂散条目(外键为 NULL 的条目)应该列在额外的行中(y2 和示例中的 z4)。
事实证明,这将是一个简单的两步 FULL JOIN
,在 PostgreSQL 中:
SELECT table1.id, table1.x, table2.y, table3.z
FROM table1
FULL JOIN table2
ON table2.Foreign_Id = table1.id
FULL JOIN table3
ON table3.Foreign_Id = table1.id
ORDER BY table1.id, table2.id, table3.id;
感谢来自 freenode 的人 #sql 指出这个等效的 MySQL 查询,避免使用 FULL JOIN
:
SELECT id1, x, y, z FROM (
SELECT table1.id as id1, table1.x, table2.id as id2, table2.y, table3.id as id3, table3.z
FROM table1
LEFT JOIN table2
ON table2.Foreign_Id = table1.id
LEFT JOIN table3
ON table3.Foreign_Id = table1.id
UNION ALL
SELECT NULL, NULL, table2.id, table2.y, NULL, NULL
FROM table2 WHERE NOT EXISTS (SELECT 1 FROM table1 WHERE table1.id = table2.Foreign_Id)
UNION ALL
SELECT NULL, NULL, NULL, NULL, table3.id, table3.z
FROM table3 WHERE NOT EXISTS (SELECT 1 FROM table1 WHERE table1.id = table3.Foreign_Id)
ORDER BY id1, id2, id3 ) AS T
假设我们需要对表 1-3 执行两次 FULL JOIN
查询(在 PostgreSQL 术语中),其中表 2 和表 3 都有指向表 1 的外键。这将适用于 MySQL,其中 FULL JOIN
不可用。因此必须找到解决方法。
从 LEFT JOIN
s 开始,以下代码按照 (1) 中的描述工作:
SELECT table1.ID, table1.x, table2.y, table3.z
FROM (table1
LEFT JOIN table2
ON table1.ID = table2.FOREIGN_ID)
LEFT JOIN table3
ON table1.ID = table3.FOREIGN_ID
在 (2) 之后,我能够使用 UNION
语句为单个连接模拟完整的外部连接:
SELECT table1.ID, table1.x, table2.y
FROM table1
LEFT JOIN table2
ON table1.ID = table2.FOREIGN_ID
UNION
SELECT table1.ID, table1.x, table2.y
FROM table1
RIGHT JOIN table2
ON table1.ID = table2.FOREIGN_ID
屈服
和
SELECT table1.ID, table1.x, table3.z
FROM table1
LEFT JOIN table3
ON table1.ID = table3.FOREIGN_ID
UNION
SELECT table1.ID, table1.x, table3.z
FROM table1
RIGHT JOIN table3
ON table1.ID = table3.FOREIGN_ID
ORDER BY ID
屈服
我需要有关如何从此处获取此输出的建议:
也就是说,通过外键引用表 1 中的条目的结果行应该正确连接,而表 2 和表 3 中的杂散条目(外键为 NULL 的条目)应该列在额外的行中(y2 和示例中的 z4)。
事实证明,这将是一个简单的两步 FULL JOIN
,在 PostgreSQL 中:
SELECT table1.id, table1.x, table2.y, table3.z
FROM table1
FULL JOIN table2
ON table2.Foreign_Id = table1.id
FULL JOIN table3
ON table3.Foreign_Id = table1.id
ORDER BY table1.id, table2.id, table3.id;
感谢来自 freenode 的人 #sql 指出这个等效的 MySQL 查询,避免使用 FULL JOIN
:
SELECT id1, x, y, z FROM (
SELECT table1.id as id1, table1.x, table2.id as id2, table2.y, table3.id as id3, table3.z
FROM table1
LEFT JOIN table2
ON table2.Foreign_Id = table1.id
LEFT JOIN table3
ON table3.Foreign_Id = table1.id
UNION ALL
SELECT NULL, NULL, table2.id, table2.y, NULL, NULL
FROM table2 WHERE NOT EXISTS (SELECT 1 FROM table1 WHERE table1.id = table2.Foreign_Id)
UNION ALL
SELECT NULL, NULL, NULL, NULL, table3.id, table3.z
FROM table3 WHERE NOT EXISTS (SELECT 1 FROM table1 WHERE table1.id = table3.Foreign_Id)
ORDER BY id1, id2, id3 ) AS T