SQL 中的三向差异
Three-Way Diff in SQL
我有三个 SQL table(A
、B
和 C
),代表数据集的三个不同版本。我想设计一个 SQL 查询,其作用是提取 rows/tuples 的 ID,其值在所有三个 table 中都不同。 (如果存在记录不共享相同值的字段,则两条记录不同。)为简单起见,我们假设 A
、B
和 C
各有 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 by
和having
:
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
列为主(或唯一)键。
我有三个 SQL table(A
、B
和 C
),代表数据集的三个不同版本。我想设计一个 SQL 查询,其作用是提取 rows/tuples 的 ID,其值在所有三个 table 中都不同。 (如果存在记录不共享相同值的字段,则两条记录不同。)为简单起见,我们假设 A
、B
和 C
各有 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 by
和having
:
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
列为主(或唯一)键。