INとEXISTSの使い分け
広告
うまさん
(No.1)
SQLのINとEXISTSの使い分けについて質問させてください
どちらも同じ結果を求められるようなのですが
EXISTS、同じテーブル内での検索では使わない
IN、同じテーブル内の検索でのみ使う
といった使い分けでも大丈夫でしょうか?
チューニングの観点からだと、明確に使い分けされているみたいなのですが、、
INは、外側のテーブルのデータ量が多く、内部のテーブルのデータ量が多い場合に利用する
EXISTSは、外側のテーブルのデータ量が少なく、内部のテーブルのデータ量が多い場合に利用する
どちらも同じ結果を求められるようなのですが
EXISTS、同じテーブル内での検索では使わない
IN、同じテーブル内の検索でのみ使う
といった使い分けでも大丈夫でしょうか?
チューニングの観点からだと、明確に使い分けされているみたいなのですが、、
INは、外側のテーブルのデータ量が多く、内部のテーブルのデータ量が多い場合に利用する
EXISTSは、外側のテーブルのデータ量が少なく、内部のテーブルのデータ量が多い場合に利用する
2021.04.10 16:54
関数従属さん
★AP シルバーマイスター
(No.2)
ご質問の観点とは違うかもしれませんが、
EXISTS句は存在するかどうかの判定、
IN句は条件の内どれかに当てはまるデータの取得、
ということで以下の使い分けがあるのかと思います。
・IN句は値も使用可能
SELECT テーブル1.*
FROM テーブル1
WHERE テーブル1.項目A IN ('XXX','YYY');
・EXISTS句は複数の結合キー条件による存在判定が可能
SELECT テーブル1.*
FROM テーブル1
WHERE EXISTS (
SELECT *
FROM テーブル2
WHERE テーブル2.項目A = テーブル1.項目A
AND テーブル2.項目B = テーブル1.項目B
);
※IN句、EXISTS句ともに単一キー条件による判定は可能です。
例えばテーブル2に存在するテーブル1のデータを取得(キーは項目A)だと以下になります。
(IN句)
SELECT テーブル1.*
FROM テーブル1
WHERE テーブル1.項目A IN (SELECT テーブル2.項目A FROM テーブル2);
(EXISTS句)
SELECT テーブル1.*
FROM テーブル1
WHERE EXISTS (
SELECT *
FROM テーブル2
WHERE テーブル2.項目A = テーブル1.項目A
);
EXISTS句は存在するかどうかの判定、
IN句は条件の内どれかに当てはまるデータの取得、
ということで以下の使い分けがあるのかと思います。
・IN句は値も使用可能
SELECT テーブル1.*
FROM テーブル1
WHERE テーブル1.項目A IN ('XXX','YYY');
・EXISTS句は複数の結合キー条件による存在判定が可能
SELECT テーブル1.*
FROM テーブル1
WHERE EXISTS (
SELECT *
FROM テーブル2
WHERE テーブル2.項目A = テーブル1.項目A
AND テーブル2.項目B = テーブル1.項目B
);
※IN句、EXISTS句ともに単一キー条件による判定は可能です。
例えばテーブル2に存在するテーブル1のデータを取得(キーは項目A)だと以下になります。
(IN句)
SELECT テーブル1.*
FROM テーブル1
WHERE テーブル1.項目A IN (SELECT テーブル2.項目A FROM テーブル2);
(EXISTS句)
SELECT テーブル1.*
FROM テーブル1
WHERE EXISTS (
SELECT *
FROM テーブル2
WHERE テーブル2.項目A = テーブル1.項目A
);
2021.04.11 17:22
うまさん
(No.3)
複数の条件を指定する場合はEXISTSということですね
ご回答、ありがとうございます
ご回答、ありがとうございます
2021.04.11 20:20
GinSanaさん
★AP プラチナマイスター
(No.4)
この投稿は投稿者により削除されました。(2021.04.12 07:47)
2021.04.12 07:47
GinSanaさん
★AP プラチナマイスター
(No.5)
パフォーマンスの話をすると、だいたい目安がINの場合判定対象が1000件超えするとパフォーマンス落ちして(Oracleならそうらしいけど、まずそんな引数を指定しない)・・・とか、
遠い昔はEXISTSの方が(NOT EXISTSではない)速いとかありましたが、いまやオプティマイザの進化によりどっこいです。postgresもいまやどっこいですね。ついでにいうと、IN句の引数は、よく出てくる(引っかけたい)キーワードを左にやっておくと、引っ掛かった時点で検索が終わるので、そういう調整も出来ます。
でも、件数が多いと遅くなる(EXISTSの場合、フルスキャンで見つかった時点で返ってくるので、UNIX/GNU Linuxのgrep -qみたいなもんです)のは確かなので、実際はINNER JOIN(内部結合)で振り落とします。そのほうがよほど速い。
だから、EXISTSって使うか?っていうと、自分はあまり使わないですね。周りは使いたがるんですが・・・。
遠い昔はEXISTSの方が(NOT EXISTSではない)速いとかありましたが、いまやオプティマイザの進化によりどっこいです。postgresもいまやどっこいですね。ついでにいうと、IN句の引数は、よく出てくる(引っかけたい)キーワードを左にやっておくと、引っ掛かった時点で検索が終わるので、そういう調整も出来ます。
でも、件数が多いと遅くなる(EXISTSの場合、フルスキャンで見つかった時点で返ってくるので、UNIX/GNU Linuxのgrep -qみたいなもんです)のは確かなので、実際はINNER JOIN(内部結合)で振り落とします。そのほうがよほど速い。
だから、EXISTSって使うか?っていうと、自分はあまり使わないですね。周りは使いたがるんですが・・・。
2021.04.12 07:47
うまさん
(No.6)
INもEXISTSも処理速度は同じくらいなのですね
さらに、EXISTSよりINNER JOINの方が速いと
DBスペシャリストの取得を目標にしているので勉強になりました
ありがとうございます
さらに、EXISTSよりINNER JOINの方が速いと
DBスペシャリストの取得を目標にしているので勉強になりました
ありがとうございます
2021.04.12 12:43
GinSanaさん
★AP プラチナマイスター
(No.7)
ちなみに、NOT EXISTSの代替は、LEFT JOINして、結合テーブルのカラムがNULLになったものをWHERE句のIS NULLで取ると同じことが出来ます。
2021.04.12 13:22
返信投稿用フォーム
スパム防止のためにスレッド作成日から30日経過したスレッドへの書込みはできません。