SQL中交集的补充

Omr*_*mri 3 sql oracle join intersection

我正在使用Oracle SQL,我有一个关于join命令的基本问题.

我有5张桌子.它们中的每一个都与主键具有相同的列:ID (int).让我们看看以下查询:

select count(*) from table_a - 100 records
select count(*) from table_c - 200 records
select count(*) from table_c - 150 records
select count(*) from table_d - 100 records
select count(*) from table_e - 120 records
Run Code Online (Sandbox Code Playgroud)
select * -- 88 records
 from table_a a
  inner join table b
    on a.id = b.id
  inner join table c
    on a.id = c.id
  inner join table d
    on a.id = d.id
  inner join table e
    on a.id = e.id
Run Code Online (Sandbox Code Playgroud)

在这种情况下,如果其中一个表不包含某个ID(即使其中包含其余的ID),许多记录也无法包含在输出中.我怎么知道这些"坏"记录是什么?它实际上是我认为的交叉点的补充.

我想知道每个案例的问题记录和表格是什么.例如:ID 123是一个"坏"记录,因为它不包含在table_c中,但包含在其余表中.ID 321是一个有问题的记录,因为它包含在除table_d之外的所有表中.

Syl*_*oux 6

您可能正在寻找所有表之间的对称差异.

要解决这类问题而不太聪明,你需要FULL OUTER JOIN ... USING:

SELECT id
    FROM table_a
    FULL OUTER JOIN table_b USING(id) 
    FULL OUTER JOIN table_c USING(id) 
    FULL OUTER JOIN table_d USING(id) 
    FULL OUTER JOIN table_e USING(id) 
WHERE table_a.ROWID IS NULL
   OR table_b.ROWID IS NULL
   OR table_c.ROWID IS NULL
   OR table_d.ROWID IS NULL
   OR table_e.ROWID IS NULL;
Run Code Online (Sandbox Code Playgroud)

FULL OUTER JOIN会返回满足连接条件(像一个普通的所有行JOIN),以及所有的行没有相应的行.该USING条款嵌入COALESCE了equijoin专栏.


另一种选择是使用反连接:

SELECT id
    FROM table_a
    FULL OUTER JOIN table_b USING(id) 
    FULL OUTER JOIN table_c USING(id) 
    FULL OUTER JOIN table_d USING(id) 
    FULL OUTER JOIN table_e USING(id) 
WHERE id NOT IN (
    SELECT id
        FROM table_a
        INNER JOIN table_b USING(id) 
        INNER JOIN table_c USING(id) 
        INNER JOIN table_d USING(id) 
        INNER JOIN table_e USING(id) 
)
Run Code Online (Sandbox Code Playgroud)

基本上,这将构建联合所有集合减去所有集合的交集.

在图形上,您可以比较INNER JOINOUTER JOIN(在3个表上仅为了便于表示):

内部联接完全外部加入


考虑到测试用例:

ID    TABLE_A TABLE_B TABLE_C TABLE_D TABLE_E
1     *       -       -       -       -
2     -       *       *       *       *
3     *       -       -       *       -
4     *       *       *       *       *
Run Code Online (Sandbox Code Playgroud)

*-缺少条目的表中的值

两个查询都将产生:

ID
1
3
2
Run Code Online (Sandbox Code Playgroud)

如果需要表格结果,可以通过添加一组CASE表达式来调整其中一个查询.像这样的东西:

SELECT ID,
    CASE when table_a.rowid is not null then 1 else 0 END table_a,
    CASE when table_b.rowid is not null then 1 else 0 END table_b,
    CASE when table_c.rowid is not null then 1 else 0 END table_c,
    CASE when table_d.rowid is not null then 1 else 0 END table_d,
    CASE when table_e.rowid is not null then 1 else 0 END table_e
FROM table_a
    FULL OUTER JOIN table_b USING(id) 
    FULL OUTER JOIN table_c USING(id) 
    FULL OUTER JOIN table_d USING(id) 
    FULL OUTER JOIN table_e USING(id) 
WHERE table_a.ROWID IS NULL
   OR table_b.ROWID IS NULL
   OR table_c.ROWID IS NULL
   OR table_d.ROWID IS NULL
   OR table_e.ROWID IS NULL;
Run Code Online (Sandbox Code Playgroud)

生产:

ID    TABLE_A TABLE_B TABLE_C TABLE_D TABLE_E
1     1       0       0       0       0
3     1       0       0       1       0
2     0       1       1       1       1
Run Code Online (Sandbox Code Playgroud)

10缺少条目的表中的值