SQL 中的三向差异

Three-Way Diff in SQL

我有三个 SQL table(ABC),代表数据集的三个不同版本。我想设计一个 SQL 查询,其作用是提取 rows/tuples 的 ID,其值在所有三个 table 中都不同。 (如果存在记录不共享相同值的字段,则两条记录不同。)为简单起见,我们假设 ABC 各有 N 条记录 ID 范围从 1 到 N,因此对于从 1 到 N 的每个 ID,每个 table 中都有一个具有该 ID 的记录。

在 SQL 中执行此操作的最有效方法是什么?一种方法是做类似

的事情
(SELECT id FROM 
((SELECT * FROM A EXCEPT SELECT * FROM B) EXCEPT (SELECT * FROM C)) result)
EXCEPT
(SELECT id FROM
((SELECT * FROM A) INTERSECT (SELECT * FROM B)) result2)

基本上我在上面所做的是首先找到 A 中的版本与 B 中的版本和 C 中的版本不同的记录的 ID(在我写的 SQL 查询的前两行)。剩下的就是过滤掉 B 中的版本与 C 中的版本相匹配的记录 ID(在最后两行中完成)。但这似乎非常低效;有没有更好更简洁的方法?

注意:我在这里使用 PostgreSQL 语法。

您可以按如下方式使用group byhaving

select id from
(select * from A
union select * from B
union select * from C)
group by id
-- use characters that you know will not appear in this columns for concat
having count(distinct column1 || '#~#' || column2 || '#~#' || column3) = 3

我会这样做:

select id, 
       a.id is null as "missing in a",
       b.id is null as "missing in b",
       c.id is null as "missing in c",
       a is distinct from b as "a and b different",
       a is distinct from c as "a and c different",
       b is distinct from c as "b and c different"
from a 
  full join b using (id)
  full join c using (id) 
where a is distinct from b
   or b is distinct from c
   or a is distinct from c   

假定 id 列为主(或唯一)键。

Online example