我想在MySQL中进行完全的外部连接。这可能吗?MySQL是否支持完全外部联接?


当前回答

您在MySQL中没有完全联接,但您可以模拟它们。

对于从堆栈溢出问题中转录的代码示例,您有:

对于两个表t1、t2:

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id

上面的查询适用于完全外部联接操作不会产生任何重复行的特殊情况。上面的查询依赖于UNION集合运算符来删除查询模式引入的重复行。通过对第二个查询使用反连接模式,然后使用UNION ALL集合运算符组合这两个集合,可以避免引入重复的行。在更一般的情况下,如果完全外部联接将返回重复的行,我们可以这样做:

SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION ALL
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id
WHERE t1.id IS NULL

其他回答

这也是可能的,但您必须在select中提到相同的字段名。

SELECT t1.name, t2.name FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT t1.name, t2.name FROM t2
LEFT JOIN t1 ON t1.id = t2.id
SELECT
    a.name,
    b.title
FROM
    author AS a
LEFT JOIN
    book AS b
    ON a.id = b.author_id
UNION
SELECT
    a.name,
    b.title
FROM
    author AS a
RIGHT JOIN
    book AS b
    ON a.id = b.author_id

前面的答案实际上都不正确,因为当存在重复值时,它们不遵循语义。

对于查询,例如(来自此副本):

SELECT * FROM t1 FULL OUTER JOIN t2 ON t1.Name = t2.Name;

正确的等效值为:

SELECT t1.*, t2.*
FROM (SELECT name FROM t1 UNION  -- This is intentionally UNION to remove duplicates
      SELECT name FROM t2
     ) n LEFT JOIN
     t1
     ON t1.name = n.name LEFT JOIN
     t2
     ON t2.name = n.name;

如果需要使用NULL值(这可能也是必要的),则使用NULL安全比较运算符<=>而不是=。

我修复了响应,工作包括所有行(基于Pavle Lekic的响应):

    (
    SELECT a.* FROM tablea a
    LEFT JOIN tableb b ON a.`key` = b.key
    WHERE b.`key` is null
    )
    UNION ALL
    (
    SELECT a.* FROM tablea a
    LEFT JOIN tableb b ON a.`key` = b.key
    where  a.`key` = b.`key`
    )
    UNION ALL
    (
    SELECT b.* FROM tablea a
    right JOIN tableb b ON b.`key` = a.key
    WHERE a.`key` is null
    );

在SQLite中,您应该执行以下操作:

SELECT * 
FROM leftTable lt 
LEFT JOIN rightTable rt ON lt.id = rt.lrid 
UNION
SELECT lt.*, rl.*  -- To match column set
FROM rightTable rt 
LEFT JOIN  leftTable lt ON lt.id = rt.lrid