如何在 SQLite 中进行 FULL OUTER JOIN?

问题描述 投票:0回答:5

SQLite 仅支持 INNER JOIN 和 LEFT JOIN。如何进行完整外部连接?

sql sqlite join full-outer-join
5个回答
104
投票

是的。请参阅 Wikipedia 上的联接 (SQL) > 外联接 > 完全外联接文章。

SELECT employee.*, department.*
FROM   employee 
       LEFT JOIN department 
          ON employee.DepartmentID = department.DepartmentID
UNION ALL
SELECT employee.*, department.*
FROM   department
       LEFT JOIN employee
          ON employee.DepartmentID = department.DepartmentID
WHERE  employee.DepartmentID IS NULL

23
投票

从 SQLite 3.39.0 开始原生支持 FULL OUTER JOIN:

2.1。输入数据的确定(FROM 子句处理)

“FULL JOIN”或“FULL OUTER JOIN”是“LEFT JOIN”和“RIGHT JOIN”的组合。为左侧数据集中与右侧不匹配的行以及右侧数据集中与左侧不匹配的每一行添加额外的输出行。不匹配的列用 NULL 填充。


演示:

CREATE TABLE t1 AS
SELECT 1 AS id, 'A' AS col UNION
SELECT 2 AS id, 'B' AS col;

CREATE TABLE t2 AS
SELECT 1 AS id, 999 AS val UNION
SELECT 3 AS id, 100 AS val;

查询:

SELECT *
FROM t1
FULL JOIN t2
  ON t1.id = t2.id;

db<>小提琴演示


11
投票

与 Jonathan Leffler 在 Mark Byers 的 answer 中的 comment 一起运行,这里有一个替代答案,它使用

UNION
而不是
UNION ALL

SELECT Table1.*, Table2.* FROM Table1 LEFT JOIN Table2 ON Table1.Column1A = Table2.Column2A
UNION
SELECT Table1.*, Table2.* FROM Table2 LEFT JOIN Table1 ON Table1.Column1A = Table2.Column2A

注释

  1. UNION
    从结果集中删除重复行,因此不需要像
    WHERE Table1.Column1A IS NULL
    那样在
    UNION
    的右侧添加额外的
    UNION ALL
  2. 如果您愿意,可以使用
    LEFT OUTER JOIN
    代替
    LEFT JOIN
    。两者没有区别。

1
投票

对于人们来说,寻找答案来模拟 Distinct Full Outer Join: 由于事实上,SQLite 既不支持完全外连接,也不支持右连接,所以我必须模拟一个不同的完全外连接/反向内连接(无论你如何称呼它)。 下面的维恩图显示了预期的输出:


为了接收此预期输出,我组合了两个 Left Join 子句(该示例指的是两个相同的构建表,但数据部分不同。我只想输出出现在表 A 或表 B 中的数据)。

SELECT A.flightNumber, A.offblockTime, A.airspaceCount, A.departure, A.arrival FROM D2flights A
    LEFT JOIN D1flights B
        ON A.flightNumber = B.flightNumber
        WHERE B.flightNumber IS NULL
UNION 
SELECT A.flightNumber, A.offblockTime, A.airspaceCount,  A.departure, A.arrival FROM D1flights A
    LEFT JOIN D2flights B
        ON A.flightNumber = B.flightNumber
        WHERE B.flightNumber IS NULL

上面的 SQLite 语句在一次查询中返回预期结果。看来,UNION 子句也通过 flightNumber 列对输出进行排序。

代码已使用 SQLite 版本 3.32.2 进行测试


0
投票

我将迟来地投入我的 2 美分。考虑下面 2 个简单的表 people1 和 people2:

   id   name age
0   1    teo  59
1   2   niko  57
2   3  maria  54 


    id   name weight
0   1    teo    186
1   2  maria    125
2   3    evi    108

首先,我们创建一个临时视图 v_all,在其中我们使用 UNION 连接两个相对的 LEFT JOINS,如下所示:

CREATE TEMP VIEW v_all AS
              SELECT p1.name AS name1, p1.age,
                    p2.name AS name2, p2.weight
              FROM people1 p1
              LEFT JOIN people2 AS p2 
              USING (name)
              UNION
              SELECT p1.name AS name1, p1.age,
                  p2.name AS name2, p2.weight
              FROM people2 AS p2
              LEFT JOIN people1 AS p1
              USING (name);

但是,我们最终得到 2 个名称列,name1 和 name2,它们可能具有空值或相等的值。我们想要的是将 name1 和 name2 组合在一个列名中。我们可以使用 CASE 查询来做到这一点,如下所示:

SELECT age,weight,
                CASE
                  WHEN name1 IS NULL
                    THEN name2
                  WHEN name2 IS NULL
                    THEN name1
                  WHEN name1=name2
                    THEN name1
                END name
              FROM v_all

我们最终得到:

      name weight   age
0    evi    108  None
1  maria    125    54
2   niko   None    57
3    teo    186    59

当然,您可以将两者组合在一个查询中,而无需创建临时视图。我避免这样做,是为了强调仅 2 个左连接和一个并集的不足,这是我迄今为止所看到的建议。

© www.soinside.com 2019 - 2024. All rights reserved.