CHECKSUM table
之类的东西。我发现http://www.besttechtools.com/articles/article/sql-query-to-check-two-tables-have-identical-data,但是我不理解所使用的逻辑。背景:我重新编写了一些数据库生成代码,因此需要检查新旧代码是否产生相同的结果。
#1 楼
一种选择是以以下形式在两个表之间使用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 ;
例如:
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 ;
将返回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 ;
返回希望计数为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 ;
评论
如果val可为空,这不会失败吗?
–阿米德·戈德斯坦
19年5月2日,14:15
@AmitGoldstein-空值将是一个问题。请参阅我的附录,以寻求一种可能的解决方案。
– gsiems
19年5月3日14:56
#2 楼
您可以使用EXCEPT
运算符。例如,如果表具有相同的结构,则以下内容将返回一个表中的所有行,而不返回另一表中的所有行(如果表具有相同的数据,则返回0行):或使用
EXISTS
返回布尔值或带有两个可能结果之一的字符串:(TABLE a EXCEPT TABLE b)
UNION ALL
(TABLE b EXCEPT TABLE a) ;
在SQLfiddle上测试/>
还不是
EXCEPT
会删除重复项(如果您的表具有PRIMARY KEY
或UNIQUE
约束,那不应该担心,但是如果您正在比较可能产生重复行的任意查询的结果,则可能是这样。) br /> EXCEPT
关键字所做的另一件事是将NULL
值视为相同,因此,如果表A
的行包含(1,2,NULL)
,而表B
的行包含(1,2,NULL)
,则第一个查询将不显示这些行,如果两个表都没有其他行,则第二个查询将返回'same'
。如果要计算这样的行与s不同,您可以对gsiems的
FULL JOIN
答案使用变体,以获取所有(不同的)行:SELECT CASE WHEN EXISTS (TABLE a EXCEPT TABLE b)
OR EXISTS (TABLE b EXCEPT TABLE a)
THEN 'different'
ELSE 'same'
END AS result ;
,并获得是/否的答案:
SELECT *
FROM a NATURAL FULL JOIN b
WHERE a.some_not_null_column IS NULL
OR b.some_not_null_column IS NULL ;
如果两个表的所有列都不为空,则两种方法将给出相同的答案。
评论
不确定是否有一些更有效的方法。
–超立方体ᵀᴹ
2014年7月29日上午10:16
@FaheemMitha,您可以使用它比较少于所有的列。只需使用SELECT
–超立方体ᵀᴹ
2014年7月29日在15:29
EXCEPT查询很漂亮!
–欧文·布兰德斯特(Erwin Brandstetter)
2014年7月30日在1:30
EXCEPT查询很贴心!
– sharadov
18/09/20在22:01
这个答案是最好的
– Oto Shavadze
20年5月15日在8:20
#3 楼
您需要Except子句类似
SELECT * FROM first_table
EXCEPT
SELECT * FROM second_table
,这将从第一张表返回所有不在第二张表中的行
#4 楼
使用except
是查找表1中而不是表2中的内容(反之亦然)并将结果并集的关键。如果它们相同,则计数为零。;with CTE1 AS
(
(
select column1, column2 from Table1
except
select column1, column2 from Table2
)
UNION
(
select column1, column2 from Table2
except
select column1, column2 from Table1
)
)
Select count(*) From CTE1 -- If identical count should be 0.
#5 楼
查看链接的代码,您将无法理解:select count(*) from
(
select * From EmpDtl1
union
select * From EmpDtl2
)
秘密的调味品是使用
union
而不是union all
。前者仅保留不同的行,而后者则保留重复的行(参考)。换句话说,嵌套查询说“给我EmpDtl1中的所有行和列,以及EmpDtl1中尚未存在的所有行和列”。当且仅当EmpDtl2不对结果贡献任何行(即两个表相同)时,此子查询的计数才等于EmpDtl1的计数。或者,按键顺序将表转储到两个文本文件,并使用您选择的比较工具。评论
当EmpDtl2的行少于EmpDtl1且所有现有行确实存在于EmpDtl1中时,这将不会检测到这种情况。
– a_horse_with_no_name
2014年7月30日下午13:14
评论
您可以使用EXCEPT,检查以下问题:比较SQL中两个大型数据集的有效方法pg_comparator进行有效的表内容比较和同步
@natmaka这应该是一个单独的答案吗?