2009-06-04 6 views
46

mysql以外のoracle diff: how to compare two tables?と同じです。は、mysqlの2つのテーブルの相違点を比較します。

レイアウトが同じですが、異なるデータを含む可能性のある2つのテーブルt1とt2があるとします。

これら2つのテーブルを比較する最も良い方法は何ですか?

より正確には、私は私に語った、単純なSQLクエリを把握しようとしているT1の1行からのデータは、T2に対応する行のデータと異なる場合

それは私が表示されます交点もマイナスも使用できません。私は

SELECT * FROM robot intersect SELECT * FROM tbd_robot 

をしようとすると、私はエラーコードを取得する:

[エラーコード:1064、SQL状態:42000]あなたのSQL 構文でエラーが発生しています。 1

ラインで「tbd_robot SELECT * FROM」近くで使用する権利構文についてはMySQLサーバのバージョン に対応マニュアルを確認し、私は文法的に間違って何かをやっていますか?そうでない場合は、別のクエリを使用できますか?

編集:また、私は無料版のDbVisualizerを使って質問しています。それが要因かもしれないかどうかは分かりません。

答えて

65

INTERSECTニーズ:

SELECT 'robot' AS `set`, r.* 
FROM robot r 
WHERE ROW(r.col1, r.col2, …) NOT IN 
     (
     SELECT * 
     FROM tbd_robot 
     ) 
UNION ALL 
SELECT 'tbd_robot' AS `set`, t.* 
FROM tbd_robot t 
WHERE ROW(t.col1, t.col2, …) NOT IN 
     (
     SELECT * 
     FROM robot 
     ) 

編集:言葉の周りに `を追加しました:私が見つけ

+1

素晴らしいです、ありがとう!どうやら、私は "セットとして"の部分が必要ではなかったが、今働いて – echoblaze

+0

素晴らしい!これが私が探していたものです。 また、ROW(...)IN(...)のことについても知りました – Imdad

+2

すべてのフィールドを記述する必要はありません。 – Veve

53

UNIONを使用して手動で交差を構築できます。両方の表に独自のフィールドがあると簡単です(例: ID:

SELECT * FROM T1 
WHERE ID NOT IN (SELECT ID FROM T2) 

UNION 

SELECT * FROM T2 
WHERE ID NOT IN (SELECT ID FROM T1) 

あなたはユニークな値を持っていない場合、あなたはまだだけではなくIDのすべてのフィールドをチェックし、使用AND(例えばID NOT IN(それらを接続するために上記のコードを拡張することができます。 MySQLでエミュレートする。)とOTHER_FIELD NOT IN(...)など)

+2

すごい答えです。 –

+1

エレガントなソリューション、@Roee Adler! – Chubaka

+0

ありがとうございます。これが有効です。 –

8

を設定しますハイムの答えに基づいて、このlink

SELECT MIN (tbl_name) AS tbl_name, PK, column_list 
FROM 
(
    SELECT ' source_table ' as tbl_name, S.PK, S.column_list 
    FROM source_table AS S 
    UNION ALL 
    SELECT 'destination_table' as tbl_name, D.PK, D.column_list 
    FROM destination_table AS D 
) AS alias_table 
GROUP BY PK, column_list 
HAVING COUNT(*) = 1 
ORDER BY PK 
+1

こんにちは、+1。私はまったく同じものを探していた。 – Hussain

+0

@ haim-evgi重複を無視します。テーブルには行があり、別のテーブルにはこのような2つの行があるので、これは無視されます。両方のテーブルにPKフィールドがないことを考慮してください。この場合、私たちはどのように対処しますか? –

+0

私は '' COUNT(*) ''の代わりに '' COUNT(*) ''を使用しなければなりませんでした。 – Rolf

2

内の別の解決策は、私がテストし、2つのデータベース間のすべての違いを表示するには、PHPコードを作成しました。 これは、テーブルがソースデータベースまたはテストデータベースに存在する場合にも表示されます。 詳細を変更するには、<>変数の内容を変更する必要があります。

<?php 

    $User = "<DatabaseUser>"; 
    $Pass = "<DatabasePassword>"; 
    $SourceDB = "<SourceDatabase>"; 
    $TestDB = "<DatabaseToTest>"; 

    $link = new mysqli("p:". "localhost", $User, $Pass, ""); 

    if (mysqli_connect_error()) { 

     die('Connect Error ('. mysqli_connect_errno() .') '. mysqli_connect_error()); 

    } 

    mysqli_set_charset($link, "utf8"); 
    mb_language("uni"); 
    mb_internal_encoding("UTF-8"); 

    $sQuery = 'SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="'. $SourceDB .'";'; 

    $SourceDB_Content = query($link, $sQuery); 

    if (!is_array($SourceDB_Content)) { 

     echo "Table $SourceDB cannot be accessed"; 
     exit(0); 

    } 

    $sQuery = 'SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="'. $TestDB .'";'; 

    $TestDB_Content = query($link, $sQuery); 

    if (!is_array($TestDB_Content)) { 

     echo "Table $TestDB cannot be accessed"; 
     exit(0); 

    } 

    $SourceDB_Tables = array(); 
    foreach($SourceDB_Content as $item) { 
     $SourceDB_Tables[] = $item["TABLE_NAME"]; 
    } 

    $TestDB_Tables = array(); 
    foreach($TestDB_Content as $item) { 
     $TestDB_Tables[] = $item["TABLE_NAME"]; 
    } 
    //var_dump($SourceDB_Tables, $TestDB_Tables); 
    $LookupTables = array_merge($SourceDB_Tables, $TestDB_Tables); 
    $NoOfDiscrepancies = 0; 
    echo " 

    <table border='1' width='100%'> 
    <tr> 
     <td>Table</td> 
     <td>Found in $SourceDB (". count($SourceDB_Tables) .")</td> 
     <td>Found in $TestDB (". count($TestDB_Tables) .")</td> 
     <td>Test result</td> 
    <tr> 

    "; 

    foreach($LookupTables as $table) { 

     $FoundInSourceDB = in_array($table, $SourceDB_Tables) ? 1 : 0; 
     $FoundInTestDB = in_array($table, $TestDB_Tables) ? 1 : 0; 
     echo " 

    <tr> 
     <td>$table</td> 
     <td><input type='checkbox' ". ($FoundInSourceDB == 1 ? "checked" : "") ."></td> 
     <td><input type='checkbox' ". ($FoundInTestDB == 1 ? "checked" : "") ."></td> 
     <td>". compareTables($SourceDB, $TestDB, $table) ."</td> 
    </tr> 
     "; 

    } 

    echo " 

    </table> 
    <br><br> 
    No of discrepancies found: $NoOfDiscrepancies 
    "; 


    function query($link, $q) { 

     $result = mysqli_query($link, $q); 

     $errors = mysqli_error($link); 
     if ($errors > "") { 

      echo $errors; 
      exit(0); 

     } 

     if($result == false) return false; 
     else if ($result === true) return true; 
     else { 

      $rset = array(); 

      while ($row = mysqli_fetch_assoc($result)) { 

       $rset[] = $row; 

      } 

      return $rset; 

     } 

    } 

    function compareTables($source, $test, $table) { 

     global $link; 
     global $NoOfDiscrepancies; 

     $sQuery = " 

    SELECT column_name,ordinal_position,data_type,column_type FROM 
    (
     SELECT 
      column_name,ordinal_position, 
      data_type,column_type,COUNT(1) rowcount 
     FROM information_schema.columns 
     WHERE 
     (
      (table_schema='$source' AND table_name='$table') OR 
      (table_schema='$test' AND table_name='$table') 
     ) 
     AND table_name IN ('$table') 
     GROUP BY 
      column_name,ordinal_position, 
      data_type,column_type 
     HAVING COUNT(1)=1 
    ) A;  

     "; 

     $result = query($link, $sQuery); 

     $data = ""; 
     if(is_array($result) && count($result) > 0) { 

      $NoOfDiscrepancies++; 
      $data = "<table><tr><td>column_name</td><td>ordinal_position</td><td>data_type</td><td>column_type</td></tr>"; 

      foreach($result as $item) { 

       $data .= "<tr><td>". $item["column_name"] ."</td><td>". $item["ordinal_position"] ."</td><td>". $item["data_type"] ."</td><td>". $item["column_type"] ."</td></tr>"; 

      } 

      $data .= "</table>"; 

      return $data; 

     } 
     else { 

      return "Checked but no discrepancies found!"; 

     } 

    } 

?> 
+0

+1を求めると、それを得るチャンスが減ります。スタックオーバーフローはレビューキューを持っている、人々は投票のQ&Aが好きであることを奨励されています。まともな答えはupvoteまたは2を得るかもしれません。 10のアップフォート(「素敵な答え」)、25のアップフォート:「良い答え」(シルバーバッジ)、100のアップフォート「素晴らしい答え」(ゴールドバッジ)のブロンズバッジがあります。 upvotesは通常質問、回答、トピックに応じてゆっくりと普通に起こります。多くの人が質問やあなたの答えを見ることができないように、またはショーを盗む競争的な回答かもしれないので、多数のアップフォートを得るのに数週間、数ヶ月または数年かかることがあります。 – clearlight

+0

[2分ツアー](http://stackoverflow.com/tour)をお勧めします。それはここで何が起こっているかについてのより多くの情報を与えるでしょう。挑戦のためにあなたのように聞こえ、素早く学び、良い仕事をしてください。あなたは評判とサイトの特権をすばやく増やすことができ、いくつかのバッジを使ってあなたの貢献を示すことができるはずです。がんばろう!歓迎します。 – clearlight

4
select t1.user_id,t2.user_id 
from t1 left join t2 ON t1.user_id = t2.user_id 
and t1.username=t2.username 
and t1.first_name=t2.first_name 
and t1.last_name=t2.last_name 

これを試してみてください。これは、あなたのテーブルを比較し、不一致が残っていればすべての一致するペアを見つけます。

+0

これは質問のための最高の、最も実行可能な答えです!ありがとう! –

+0

偽陽性を排除するためにifnull(t1.field_name、1)= ifnull(t2.field_name、1)を必ず使用してください。 –

関連する問題