2013-07-01 88 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的計數)

相關問題