【问题标题】:How can I compare if 2 tables have the same data?如果两个表具有相同的数据,我该如何比较?
【发布时间】:2013-07-01 19:07:08
【问题描述】:

如果我有 2 个表并且想查找它们是否具有相同的数据,那么在 MySQL 中最直接的方法是什么?
我已经阅读了有关执行相关子查询和UNION ALL 的信息,但是此查询大约有 2 页(!)并且不能真正遵循它在做什么。一定有更简单的方法。
即使它是例如使MySQL 将表数据复制到文件并执行vimdiff(我不确定这是否可能-是吗?-只是大声思考)。

更新
我只对表格数据感兴趣,而不对结构感兴趣。由于我发表的模棱两可的评论,这是为了澄清

【问题讨论】:

  • mySQL - Compare Table Rows 的可能重复项
  • 桌子有多大?如果它们足够小,您可以转储它们并比较转储文件(与diff) - 假设某些键正在适当地索引(和排序)它们......否则,显示数据库的架构,或至少表...
  • @BasileStarynkevitch:它们很大。但即使它们很小,我也不知道该怎么做你的建议。如果你把它作为答案的一部分发布,我会很感兴趣。我我会投票
  • @BasileStarynkevitch:为什么架构对此很重要?难道没有针对我的问题的特定 MySQL 解决方案吗?
  • @RobW:我对查找具有不同值的行不感兴趣。我想知道表 A 和表 B 是否完全相同

标签: mysql sql linux subquery


【解决方案1】:

如果您只想尽可能高效地判断表是否相同,请使用以下查询:

SELECT 1 FROM (
   SELECT * FROM table1
   UNION ALL
   SELECT * FROM table2
) t
GROUP BY col1, col2, col3
HAVING count(*) = 1
LIMIT 1
  • 列出GROUP BY中的所有列以比较整个表格。

  • 如果结果为空集,则两个表相同。

如果您想查看差异,请使用以下查询:

SELECT * FROM (
   SELECT 'table1' tname, col1, col2, col3 FROM table1
   UNION ALL
   SELECT 'table2' tname, col1, col2, col3 FROM table2
) t
GROUP BY col1, col2, col3
HAVING count(*) = 1
  • 在内部SELECT 中列出与GROUP BY 中相同的列,加上一列来区分这两个表。

【讨论】:

  • +1。但如果它们不相同,我将无法看到差异。
  • @Cratylus 我更新了我的答案,我添加了查询的变体以查看差异。
【解决方案2】:

只要把它扔在那里,你就可以模拟一个完整的外连接,然后返回右侧或左侧为空的行。

select t1.* 
from table1 t1
LEFT OUTER JOIN table2 t2
ON t1.col1 = t2.col1
AND t1.col2 = t2.col2
AND ...
WHERE t2.id is null
UNION
select t2.* 
from table2 t2
LEFT OUTER JOIN table1 t1
ON t2.col1 = t1.col1
AND t2.col2 = t1.col2
AND ...
WHERE t1.id is null

使用 FULL OUTER JOIN,您可以显示其他行在其他表中不可用的所有行。

【讨论】:

  • +1. 你为什么不做一个右连接并在查询的第二部分恢复顺序?
  • 没有理由,我只是偏向左joins.m
【解决方案3】:

使用以下查询:

SELECT c1 = cjoin AND c2 = cjoin equiv
FROM (SELECT COUNT(*) c1 FROM Table1) t1,
     (SELECT COUNT(*) c2 FROM Table2) t2,
     (SELECT COUNT(*) cjoin
      FROM Table1 t1
      JOIN Table2 t2
      ON t1.col1 = t2.col1 AND t1.col2 = t2.col2 AND t1.col3 = t2.col3 ...) tjoin

假设表具有唯一键,如果表相等,这将返回 equiv = 1。它没有显示差异,它只是一个二进制测试。

【讨论】:

  • 我不明白。为什么SELECT COUNT
  • 第三个子查询查找两个表中相同的行。但是,如果任一表中有额外的行,它们将不会被注意到。所以我统计了每张表的行数,如果这个数等于相等的行数,就说明没有多余的行了。
【解决方案4】:

当我遇到一个解决方案时,我正在阅读 A.Molinaro 的 SQL Cookbook。 它基于表 emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) 和一个视图 V 它具有相同的列但不同的行。 mgrcomm 列可能为 NULL,其他列则不是。 书中的解决方案很长,并没有显示所有差异,尽管这是 3.7 中陈述的问题。 我制定了我的解决方案,它更短并显示了所有差异(意味着两个表中具有不同计数的所有行)。

select * from
# those which are contained in the (distinct) union of (col1,col2,...,coln, count) of both tables:
( select empno,ename,job,mgr,hiredate,comm,deptno, count(*) cnt from emp group by empno,ename,job,mgr,hiredate,comm,deptno
   union
  select empno,ename,job,mgr,hiredate,comm,deptno, count(*) cnt from V group by empno,ename,job,mgr,hiredate,comm,deptno
) as unionOfBoth
where (empno,ename,job,mgr,hiredate,comm,deptno,cnt)
not in
# those which are contained in the intersection of both tables with the equal number of counts:
( select e.empno,e.ename,e.job,e.mgr,e.hiredate,e.comm,e.deptno,e.cnt
  from
  (select empno, ename,job,mgr,hiredate,comm,deptno, count(*) cnt from emp group by empno,ename,job,mgr,hiredate,comm,deptno) e,
  (select empno, ename,job,mgr,hiredate,comm,deptno, count(*) cnt from V group by empno,ename,job,mgr,hiredate,comm,deptno) v
  where 
   e.empno = v.empno 
   and e.ename = v.ename
   and e.job = v.job
   and ifnull(e.mgr,0) = ifnull(v.mgr,0)
   and e.hiredate = v.mgr
   and e.deptno = v.deptno
   and ifnull(e.comm,0) = ifnull(v.comm,0)
   and e.cnt = v.cnt
);

基本上,您计算两个表中的不同行并进行联合(不是全部联合)以获得 tmp.table unionBoth。然后删除两个表共有的那些行。 这里表 t1 中的两行 r1 和表 t2 中的 r2 被认为是相同的,如果 (r1,count of r1 in t1) = (r2, count of r2 in t2),相当于r1=r2(在所有列上) (t1 中 r1 的计数)=(t2 中 r2 的计数).

【讨论】:

    【解决方案5】:

    如果表格足够小,您可以将两个表格导出为 csv 文件,然后复制其中一个表格并将它们与另一个表格并排粘贴。您可以逐行查看输出是否相同。

    【讨论】:

    • 我认为 OP 希望以编程方式执行此操作。
    猜你喜欢
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    • 2020-02-20
    • 2020-06-08
    相关资源
    最近更新 更多