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 JOINs 开始,以下代码按照 (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