質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.61%

  • SQL

    2323questions

    SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

SQLでレコードの存在有無を条件にする場合、JOINを使いますか?EXISTSを使いますか?

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 12K+

anonymouskawa

score 810

SELECT *
FROM table_a a
INNER JOIN table_b b ON a.col1 = b.col1;

SELECT *
FROM table_a a
WHERE EXISTS (
    SELECT *
    FROM table_b b
    WHERE a.col1 = b.col1 
);
上記の2つのSQLは、同じ結果が返ります。

Q.あなたはJOIN派ですか?EXISTS派ですか?
どのような規模の案件を想定して頂いても構いません。
使い分けるならば、どういう場合でどちらを選択しますか?

長いこと、色々な人の意見を聞いてみたいと思っていたので、是非お気軽にご回答下さい。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+2

上記の2つのSQLは、同じ結果が返ります。 

つまり、

table_a と table_b は粒度
col1 は table_a や table_b の主キー、あるいはユニークキー
table_a と table_b は 1 対 0..1 な関係

ということですね?

もしそうなのであれば、SELECT 句を a.* にしたうえで JOIN を使うかもしれません。

特に根拠があるわけではありませんが、相関サブクエリよりもただの結合の方が RDBMS による最適化の余地がありそうな気がするからです。

例えば、EXISTS だと table_a から駆動する以外に選択肢が無さそうですが、JOIN なら table_b から駆動できるかもしれません。

もし、table_a が 100万件に対して、table_b が 100件しかないのであれば、その差は歴然だと思います(極端な例だと思いますが)。


ただ、もし、その2つのテーブルの粒度が同じではなく、1 対 0..N な関係なのだとしたら、JOIN の方には GROUP BY も必要になるはずなので、そんなことをするぐらいなら EXISTS にすると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/03 13:19

    a.*が正しいですね!
    質問のミスです。失礼しました。

    >特に根拠があるわけではありませんが、相関サブクエリよりもただの結合の方が RDBMS による最適化の余地がありそうな気がするからです。
    条件によって異なるところですが、ある特定の条件下においては、相関サブクエリはものすごく遅くなるので忌避されている(何が何でも使っちゃいけないってことはないですが)みたいですね。

    読みやすさはEXISTS(JOINは本来の用途と異なりますしね)なので、
    EXISTSが遅いという問題は早急に解決してほしいとは思います。

    ありがとうございます!

    キャンセル

checkベストアンサー

+1

理想論で言えば、table_aのカラムがメインでtable_bを絞込み条件としてのみ見る場合はEXISTSを使いたくなります。
逆に、table_b固有のカラムに興味があるようなクエリを書く場合はJOINを使います。
質問タイトルは前者に該当すると思うので、EXISTSの方が好みですかね。

後は使うDBMSの特性とパフォーマンス要件次第です。
よく話題にあがる例で言えばMySQL(特に古いバージョン)は相関サブクエリがどうしても遅くなるので、JOINに寄る事が多いです。最終的には実行計画と測定結果を見て決める話ですが。

月並みな回答ですね・・・。
私も色々な方の回答が気になります!

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/03 13:12

    回答ありがとうございます!

    >table_aのカラムがメインでtable_bを絞込み条件としてのみ見る場合はEXISTSを使いたくなります。
    >逆に、table_b固有のカラムに興味があるようなクエリを書く場合はJOINを使います。

    私もこの方針でSQLを作成していますね。
    MySQLはEXISTSの相関サブクエリを自動で解決してくれないので、
    結果的に遅くなる「ケースもありうる」なので、実行計画や測定結果、あるいは事前の予測値を元にJOINか使い分けるでしょう。
    なんでもかんでもJOINしたり「相関サブクエリは悪」という風潮は嫌ですね。

    Oracleは、JOINでもEXISTSでも同じように解決してくれるとのことで、Oracleエンジニアだと気にせずEXISTS使ってるイメージがありますねー。

    キャンセル

0

場合によりけりかと

EXISTS  : 結果にtable_b の情報を使用しない場合
JOIN : 結果にtable_b の情報を使用する場合

結果が同じでも、確か『EXISTS』の方がパフォーマンスがよい様な記事を見たことがあります。
うろ覚えですみません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/03 13:21

    回答ありがとうございます!
    EXISTSとJOINは条件次第でどちらが早いか遅いかは変わってくるので、もし新規構築時ならばレコードの分布と件数を正しく把握していないと痛い目にあいそうです。
    (今のところ、幸いにして問題がおきたことはないのですが)

    table_bの情報が必要であればJOINですが、必要がない、ただの条件として扱うのであれば、やはりEXISTSを使いたいと思っちゃいますねー。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    oracle SQL

    表のデータに「あ」から「ん」までの50音を使って 重複無くデータの更新をしたいです。 あ100 あ102 い102 あ103 あ104 い104 う104 え104 見たいな感じで

  • 解決済

    MySQLのLIKE演算で除外検索

    検索する対象のオブジェクトがあり、それに対してタグを付けて、タグを検索するようにしています。 その時除外検索をしたいのですが、 --table-- no tag 0 abc 0

  • 受付中

    SQL テーブル結合

    質問です。 DVDテーブル、レンタルテーブルがあり 一度も借りられたことのないDVDを抽出するとします。 DVDテーブルのDVDIDとレンタルテーブルのDVDIDを結合して 借

  • 解決済

    レコードが存在しないユーザー一覧を取得したい

    SQLの質問です。 user_id(int)item_id(int) という2カラムのテーブルを想定しています。 item_id=1は持っているけど(レコードが存在するけど)、

  • 解決済

    mysql 完全一致及び部分一致検索について

    ある特定カラム(例:name)に対して、完全一致で検索し、該当レコードがない場合、部分一致検索を一回のSQLクエリで実行したいのですが、可能でしょうか。 ご教授いただけると幸いです

  • 解決済

    重複したレコードのみ抽出したい

    重複したレコードのみ抽出したく下記のように書きましたが一行しか出ませんでした。目で追うと100行以上の重複レコードがあります。 SELECT a FROM table HAV

  • 解決済

    MySQL で2つの結果を比較して片方に含まれないデータを抽出したい(not existsを利用しま...

    次のような2つのSQLと結果があります・ SQL1 select d.no as no from tbl_d as d inner join tbl_e as e

  • 解決済

    SQL副問合せのFROM句で複数テーブルを使用したい

    前提・実現したいこと SQLで親テーブルに存在しないCLIENT_CDが他テーブルに存在する件数を取得するSQLを作成したいです。 各SQLのブロックで親テーブルに存在しないCLI

同じタグがついた質問を見る

  • SQL

    2323questions

    SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。