Fah*_*tha 35 postgresql duplication
这已经在 Stack Overflow 上问过了,但仅限于 MySQL。我正在使用 PostgreSQL。不幸的是(而且令人惊讶的是)PostgreSQL 似乎没有像CHECKSUM table.
PostgreSQL 解决方案会很好,但通用的解决方案会更好。我找到了http://www.besttechtools.com/articles/article/sql-query-to-check-two-tables-have-identical-data,但我不明白使用的逻辑。
背景:我重新编写了一些数据库生成代码,所以我需要检查新旧代码是否产生相同的结果。
ype*_*eᵀᴹ 39
您可以使用EXCEPT运算符。例如,如果表具有相同的结构,以下将返回一个表中的所有行而不是另一个表中的所有行(如果表具有相同的数据,则为 0 行):
(TABLE a EXCEPT TABLE b)
UNION ALL
(TABLE b EXCEPT TABLE a) ;
Run Code Online (Sandbox Code Playgroud)
或者 withEXISTS只返回一个布尔值或一个带有 2 个可能结果之一的字符串:
SELECT CASE WHEN EXISTS (TABLE a EXCEPT TABLE b)
OR EXISTS (TABLE b EXCEPT TABLE a)
THEN 'different'
ELSE 'same'
END AS result ;
Run Code Online (Sandbox Code Playgroud)
在SQLfiddle测试
也不是EXCEPT删除重复项(如果您的表有一些PRIMARY KEY或UNIQUE约束,则不必担心,但如果您正在比较可能产生重复行的任意查询的结果,则可能需要担心)。
EXCEPT关键字所做的另一件事是它将NULL值视为相同的,因此如果 tableA有一行 with(1,2,NULL)并且 tableB有一行 with (1,2,NULL),则第一个查询将不会显示这些行,'same'如果两个表没有其他行,则第二个查询将返回。
如果您想将此类行计算为不同,您可以使用 gsiemsFULL JOIN答案的变体来获取所有(不同)行:
SELECT *
FROM a NATURAL FULL JOIN b
WHERE a.some_not_null_column IS NULL
OR b.some_not_null_column IS NULL ;
Run Code Online (Sandbox Code Playgroud)
并获得是/否的答案:
SELECT CASE WHEN EXISTS
( SELECT *
FROM a NATURAL FULL JOIN b
WHERE a.some_not_null_column IS NULL
OR b.some_not_null_column IS NULL
)
THEN 'different'
ELSE 'same'
END AS result ;
Run Code Online (Sandbox Code Playgroud)
如果两个表的所有列都不可为空,则两种方法将给出相同的答案。
gsi*_*ems 29
一种选择是以以下形式在两个表之间使用 FULL OUTER JOIN :
SELECT count (1)
FROM table_a a
FULL OUTER JOIN table_b b
USING (<list of columns to compare>)
WHERE a.id IS NULL
OR b.id IS NULL ;
Run Code Online (Sandbox Code Playgroud)
例如:
CREATE TABLE a (id int, val text);
INSERT INTO a VALUES (1, 'foo'), (2, 'bar');
CREATE TABLE b (id int, val text);
INSERT INTO b VALUES (1, 'foo'), (3, 'bar');
SELECT count (1)
FROM a
FULL OUTER JOIN b
USING (id, val)
WHERE a.id IS NULL
OR b.id IS NULL ;
Run Code Online (Sandbox Code Playgroud)
将返回 2 的计数,而:
CREATE TABLE a (id int, val text);
INSERT INTO a VALUES (1, 'foo'), (2, 'bar');
CREATE TABLE b (id int, val text);
INSERT INTO b VALUES (1, 'foo'), (2, 'bar');
SELECT count (1)
FROM a
FULL OUTER JOIN b
USING (id, val)
WHERE a.id IS NULL
OR b.id IS NULL ;
Run Code Online (Sandbox Code Playgroud)
返回希望计数为 0。
我喜欢这种方法的一点是,当使用 EXISTS 时,它只需要读取每个表一次,而不是读取每个表两次。此外,这应该适用于支持完全外部联接的任何数据库(不仅仅是 Postgresql)。
我通常不鼓励使用 USING 子句,但在这种情况下,我认为它是更好的方法。
附录 2019-05-03:
如果可能的空数据存在问题(即 id 列不可为空,但 val 是),那么您可以尝试以下操作:
SELECT count (1)
FROM a
FULL OUTER JOIN b
ON ( a.id = b.id
AND a.val IS NOT DISTINCT FROM b.val )
WHERE a.id IS NULL
OR b.id IS NULL ;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
88145 次 |
| 最近记录: |