使用SQLite的全外联接

wvmv3b1j  于 2023-03-19  发布在  SQLite
关注(0)|答案(5)|浏览(224)

SQLite只有内部连接和左连接。
有没有办法用SQLite进行完全外连接?

kokeuurv

kokeuurv1#

可以。请参阅Wikipedia上的Join(SQL)〉Outer join〉Full outer join文章。

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
zpqajqem

zpqajqem2#

从SQLite 3.39.0开始,完全外部联接得到本机支持:
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;

**一个

tyky79it

tyky79it3#

根据Jonathan Leffler在Mark Byers的answer中的评论,这里有一个替代答案,它使用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从结果集中删除重复的行,因此不需要在UNION的右侧添加额外的WHERE Table1.Column1A IS NULL,而UNION ALL则需要。
    1.如果愿意,可以使用LEFT OUTER JOIN代替LEFT JOIN,两者没有区别。
iugsix8n

iugsix8n4#

对于搜索模拟 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对代码进行了测试

vddsk6oq

vddsk6oq5#

我将迟来地投入我的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);

然而,我们最终得到了两个名称列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个左连接和一个联合的不足,这是我目前看到的推荐。

相关问题