2013-07-01 85 views
0

如果我有2个表格,并且想要查找它们是否具有相同的数据,那么在MySQL中最简单的方法是什么?
我已阅读关于做相关子查询和UNION ALL,但这个查询大约2页(!),并不能真正按照它正在做什么。必须有一个更简单的方法。
即使它是例如使MySQL将表格数据复制到文件并做vimdiff(我不确定这是甚至可能的 - 是吗? - 只是大声思考)。如何比较两个表是否有相同的数据?

UPDATE
我只对表格数据感兴趣,而不是结构。这是为了澄清,由于我作出的模糊评论

+0

可能重复的[mySQL - 比较表行](http://stackoverflow.com/questions/11279108/mysql-compare-table-rows) –

+0

表有多大?如果它们足够小,则可以转储它们并比较转储文件(使用'diff') - 假设某个键正在对它们进行索引(并对其进行排序)。否则,显示数据库的架构,或者至少桌子...... –

+0

@BasileStarynkevitch:他们很大。但即使他们很小,我也不知道如何去做你的建议。如果你把它作为答案的一部分发布,我会觉得很有意思。我会赞成 – Cratylus

回答

1

只是抛出这个问题,你可以模拟一个完整的外部联接,然后返回右侧或左侧为空的行。

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,您可以显示其他行在另一个表中不可用的所有行。

+0

+ 1.为什么你没有正确加入并在查询的第二部分中恢复了订单吗? – Cratylus

+0

没理由,我只是倾向左边joins.m –

0

使用以下查询:

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如果表是相等的。它没有显示差异,它只是一个二元测试。

+0

我不明白这一点。为什么'SELECT COUNT'? – Cratylus

+0

第三个子查询查找两个表中相同的行。但是如果两个表中都有额外的行,他们将不会被注意到。所以我计算每个表中的行数,如果这等于相等的行数,则意味着没有额外的行。 – Barmar

4

如果你只是想告诉表是否相同或不尽可能有效地使用此查询:

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,加上一列来区分两个表。
+0

+ 1.但是,如果它们不相同,我就不会看到区别。 – Cratylus

+0

@Cratylus我更新了我的答案,为查看差异添加了查询的变体。 – janos

0

我正在读A.Molinaro的SQL Cookbook,当时我遇到了一个解决方案。 它是基于对表 EMP(EMPNO,ENAME,工作,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。然后你删除这两个表共有的行。 这里如果 (r1,t1中r1的计数)=(r2,t2中r2的计数),这相当于r1 = r2,则来自表t1和来自表t2的两行r1被认为是相同的(在所有列上)(t1中r1的计数)=(t2中r2的计数)

相关问题