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

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

新規登録して質問してみよう
ただいま回答率
85.48%
SQL

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

Q&A

解決済

3回答

38367閲覧

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

anonymouskawa

総合スコア856

SQL

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

0グッド

1クリップ

投稿2015/09/01 12:07

SQL

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

SQL

1SELECT * 2FROM table_a a 3WHERE EXISTS ( 4 SELECT * 5 FROM table_b b 6 WHERE a.col1 = b.col1 7);

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

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

長いこと、色々な人の意見を聞いてみたいと思っていたので、是非お気軽にご回答下さい。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

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

つまり、

  • table_atable_b は粒度
  • col1table_atable_b の主キー、あるいはユニークキー
  • table_atable_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/01 13:04

ngyuki

総合スコア4514

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

anonymouskawa

2015/09/03 04:19

a.*が正しいですね! 質問のミスです。失礼しました。 >特に根拠があるわけではありませんが、相関サブクエリよりもただの結合の方が RDBMS による最適化の余地がありそうな気がするからです。 条件によって異なるところですが、ある特定の条件下においては、相関サブクエリはものすごく遅くなるので忌避されている(何が何でも使っちゃいけないってことはないですが)みたいですね。 読みやすさはEXISTS(JOINは本来の用途と異なりますしね)なので、 EXISTSが遅いという問題は早急に解決してほしいとは思います。 ありがとうございます!
guest

0

ベストアンサー

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

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

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

投稿2015/09/01 12:41

編集2015/09/01 12:46
hy3

総合スコア594

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

anonymouskawa

2015/09/03 04:12

回答ありがとうございます! >table_aのカラムがメインでtable_bを絞込み条件としてのみ見る場合はEXISTSを使いたくなります。 >逆に、table_b固有のカラムに興味があるようなクエリを書く場合はJOINを使います。 私もこの方針でSQLを作成していますね。 MySQLはEXISTSの相関サブクエリを自動で解決してくれないので、 結果的に遅くなる「ケースもありうる」なので、実行計画や測定結果、あるいは事前の予測値を元にJOINか使い分けるでしょう。 なんでもかんでもJOINしたり「相関サブクエリは悪」という風潮は嫌ですね。 Oracleは、JOINでもEXISTSでも同じように解決してくれるとのことで、Oracleエンジニアだと気にせずEXISTS使ってるイメージがありますねー。
guest

0

場合によりけりかと

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

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

投稿2015/09/03 01:01

MasterOstrich

総合スコア12

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

anonymouskawa

2015/09/03 04:21

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問