none
2つのテーブルを比較し、異なるレコードを抽出したい RRS feed

  • 質問

  • どなたかご教示いただけますでしょうか。よろしくお願いいたします。

    SQL Server に以下のようなテーブル定義が同じで、異なる名称のテーブルがございます。

     [ID] [nchar](5) NOT NULL,
     [flg] [tinyint] NULL,
     [namae] [nvarchar](50) NULL

    テーブルA
    ID | flg | namae
    -----------------
    101|NULL | 田中
    102|1    | 鈴木
    103|0    | 近藤
    200|1    | 高田

    テーブルB
    ID | flg | namae
    -----------------
    101|NULL | 田中太郎   <--- 抽出したい (名前が追加されたため)
    102|2    | 鈴木       <--- 抽出したい (flg が変更されたため)
    103|0    | 近藤
    105|0    | 佐藤

    (ご質問)

    両テーブルに同じ ID のレコードが存在するレコードが対象で、かつ ID 以外のフィールド値でどれか一つでも異なる B テーブルのデータを抽出するクエリーはございますでしょうか。

    もしご存じの方がいらしましたら、ご教示いただけないでしょうか。よろしくお願いいたします。

    ※プログラムを作って実行すると抽出完了まで時間を要すため、クエリーでできないものか試行錯誤しましたがどうしてもできず、質問させていただいた次第です。

    2016年1月15日 14:31

回答

  • 細かいですがSQLでの否定は ! でなく NOT です。加えて NOT (expr IS NULL) は expr IS NOT NULL と書けます。以上を踏まえて

    SELECT B.ID, B.flg, B.namae
    FROM B INNER JOIN A ON B.ID = A.ID
    WHERE B.flg <> A.flg
       OR B.flg IS NULL AND A.flg IS NOT NULL
       OR B.flg IS NOT NULL AND A.flg IS NULL
       OR B.namae <> A.namae
       OR B.namae IS NULL AND A.namae IS NOT NULL
       OR B.namae IS NOT NULL AND A.namae IS NULL;
    

    かな?

    # ISNULL(B.flg <> A.flg, B.flg IS NOT NULL OR A.flg IS NOT NULL) とはできないのね…。

    • 回答としてマーク yumi08 2016年1月16日 1:24
    2016年1月15日 21:34
  • 解決しているので余計かもしれませんが、こうゆう時用の EXCEPT演算子 な気が・・・
    • 回答としてマーク yumi08 2016年1月17日 2:04
    2016年1月17日 0:21

すべての返信

  • FROM TableA A INNER JOIN TableB on a.id = b.id して、できた列を1こずつ a.flg <> b.flg AND a.namae <> b.namae ...みたいな条件を並び立てるしかないと思いますが。

    あ、NULLが含まれる列は比較文を書くのが超面倒くさくなるので、そのつもりで。
    flg項目1つなら、「(a.flg IS NULL AND ! (b.flg IS NULL)) OR (!(a.flg IS NULL) AND b.flg IS NULL) OR a.flg <> b.flg、」かな


    jzkey

    2016年1月15日 14:46
  • 以下のスレッドで私が書いたSQLが参考になるのではないかと思います。

    データのバックアップの方法について教えてください。
    https://social.msdn.microsoft.com/Forums/sqlserver/ja-JP/528cc3c4-c735-4ad0-8e3c-df1b040fd44d?forum=sqlserverja


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    2016年1月15日 15:12
  • 細かいですがSQLでの否定は ! でなく NOT です。加えて NOT (expr IS NULL) は expr IS NOT NULL と書けます。以上を踏まえて

    SELECT B.ID, B.flg, B.namae
    FROM B INNER JOIN A ON B.ID = A.ID
    WHERE B.flg <> A.flg
       OR B.flg IS NULL AND A.flg IS NOT NULL
       OR B.flg IS NOT NULL AND A.flg IS NULL
       OR B.namae <> A.namae
       OR B.namae IS NULL AND A.namae IS NOT NULL
       OR B.namae IS NOT NULL AND A.namae IS NULL;
    

    かな?

    # ISNULL(B.flg <> A.flg, B.flg IS NOT NULL OR A.flg IS NOT NULL) とはできないのね…。

    • 回答としてマーク yumi08 2016年1月16日 1:24
    2016年1月15日 21:34
  • 皆さん、多くの情報をご提供くださいまして誠にありがとうございました。

    それぞれの情報、とても有用でしたが、特に具体的なコードを記載していただいた 佐祐理 様、重ねてお礼申し上げます。

    そのまま貼り付け確認した結果、

    >FROM B INNER JOIN A ON B.ID = A.ID

    を RIGHT JOIN に変更することで、私の期待した結果が得られることを確認いたしました。

    本当にありがとうございました!

    2016年1月16日 1:33
  • それは求めている答えに対して質問文が間違っています。「両テーブルに同じ ID のレコードが存在するレコードが対象で」という条件であれば INNER JOIN が適切です。
    2016年1月16日 3:16
  • 佐祐理 さん、すみません。

    今一度、動作確認した結果、RIGHT JOIN ではなく、INNER JOIN の結果が私が期待する結果でした。

    訂正いたします。私が質問した 2 レコードが得られるクエリは、INNER JOIN  でした。

    佐祐理 さん、ありがとうございました!

    2016年1月16日 11:28
  • 解決しているので余計かもしれませんが、こうゆう時用の EXCEPT演算子 な気が・・・
    • 回答としてマーク yumi08 2016年1月17日 2:04
    2016年1月17日 0:21
  • aviator__ さん、追加情報をありがとうございます。

    まだ詳しく精査していませんが、ご指摘いただいた EXCEPT を使って以下のクエリを実行した結果、
    ざっと見た感じ、こちらも私が期待した結果が得られました。

    SELECT            B.ID, B.flg, B.namae
    FROM              A INNER JOIN
                            B ON A.ID = B.ID

    EXCEPT
     
    SELECT            A.ID, A.flg, A.namae
    FROM              A INNER JOIN
                            B ON A.ID = B.ID;

    有用な情報をご提示いただきありがとうございました!
    2016年1月17日 2:06
  • なるほど、除外するという考え方ですと、もしかしてNOTで否定するだけでよかったり…? 

    SELECT B.ID, B.flg, B.namae
    FROM B INNER JOIN A ON B.ID=A.ID
    WHERE NOT(B.flg=A.flg AND B.namae=A.namae);

    # 私は回答を提示するよりもjzkeyさんの ! を指摘したかったので…と言い訳 orz

    2016年1月17日 3:13