SQLのEXISTSとINの違いは?


443

SQL のEXISTSand IN句の違いは何ですか?

いつ使用しEXISTS、いつ使用しINますか?

回答:


224

existsキーワードは、そのように使用することができますが、実際にそれはカウントを回避する方法として意図されます:

--this statement needs to check the entire table
select count(*) from [table] where ...

--this statement is true as soon as one match is found
exists ( select * from [table] where ... )

これは、あなたが持っているところ最も有用であるifとして、条件文をexistsたくさん速くよりもすることができますcount

inあなたは合格する静的なリストを持っているところ最高使用されます。

 select * from [table]
 where [field] in (1, 2, 3)

inステートメントにテーブルがある場合は、を使用する方が理にかなっていますがjoin、ほとんどの場合それは問題になりません。クエリオプティマイザーは、どちらの方法でも同じプランを返す必要があります。一部の実装(主にMicrosoft SQL Server 2000などの古いバージョン)では、inクエリは常にネストされた結合プランを取得しますが、joinクエリは必要に応じてネスト、マージ、またはハッシュを使用します。より近代的な実装はよりスマートで、をin使用した場合でも計画を調整できます。


2
「inステートメントにテーブルがある場合、結合を使用する方が理にかなっていますが、それほど重要ではありません。クエリオプティマイザはどちらの方法でも同じプランを返します。」について詳しく説明してください。クエリオプティマイザーの部分ではなく、のJOIN代わりとして使用できる部分IN
farthVader 2015年

select * from [table] where [field] in (select [field] from [table2])と同じ結果(およびクエリプラン)を返しますselect * from [table] join [table2] on [table2].[field] = [table].[field]

@Sanderは行いません。最初のクエリはからすべての列をtable返し、2番目のクエリはtableand からすべてを返しますtable2。一部の(ほとんど古い)SQLデータベースでは、inクエリはネストされた結合として実装されjoinますが、クエリはネスト、マージ、ハッシュ化など、最も高速な方法で実行できます。
キース

2
さて、select句で列を指定する必要がありましたが、クエリは「どちらの方法でも同じプランを返す」と明記されているため、回答を更新する必要があります。

exists彼らは道もすなわちその便利なことができるので、ケースステートメント内で使用することができますselect case when exists (select 1 from emp where salary > 1000) then 1 else 0 end as sal_over_1000
smooth_smoothie

125

EXISTSクエリが結果を返したかどうかを教えてくれます。例えば:

SELECT * 
FROM Orders o 
WHERE EXISTS (
    SELECT * 
    FROM Products p 
    WHERE p.ProductNumber = o.ProductNumber)

IN 1つの値を複数の値と比較するために使用され、次のようにリテラル値を使用できます。

SELECT * 
FROM Orders 
WHERE ProductNumber IN (1, 10, 100)

次のINように、クエリ結果を句で使用することもできます。

SELECT * 
FROM Orders 
WHERE ProductNumber IN (
    SELECT ProductNumber 
    FROM Products 
    WHERE ProductInventoryQuantity > 0)

3
最後のクエリは、サブクエリが結果を返さない場合に失敗する可能性があるため、危険です。'in'句には少なくとも1つの引数が必要です...
user2054927

40
@ user2054927サブクエリが行を返さない場合、最後のクエリは行を正しく返しません-それについて何も危険ではありません!
トニーアンドリュース

最良の答え。
Aminadav Glickshtein

81

ルールオプティマイザーに基づく:

  • EXISTSINサブクエリの結果が非常に大きい場合、はよりもはるかに高速です。
  • INEXISTSサブクエリの結果が非常に小さい場合、はより高速です。

コストオプティマイザーに基づく:

  • 違いはありません。

21
あなたの議論の証拠?INがEXISTSよりも速くなるとは思いません!
Nawaz、2014年

22
@Nawaz INが常にEXISTSより遅い理由の証明はどうですか?
14

2
不適切に実装されたクエリオプティマイザー?私がしました。この(ない、まさにこのような状況が)特定のRDBMSに起こる...のようなものに見える
Haroldo_OK

1
EXISTSは純粋なブール値を返します。これは、BIT /ブール型よりも大きい文字列または値を比較する必要がある場合より常に高速です。INはブール比較である場合とそうでない場合があります。プログラミングは安定性のためにEXPLICITの使用を好むため(ACIDの一部)、EXISTSが一般的に好まれます。
clifton_h 2016年

2
なぜこれが何度も賛成されたのですか?この仮定に基づく声明が一般的に真実であるべき理由は絶対にありません。
Lukas Eder

40

私はあなたがそれらが何をしているのかを知っていると想定しているため、異なる方法で使用されているので、私はあなたの質問を次のように理解します:EXISTSの代わりにINを使用するようにSQLを書き直すのは良い考えです

それは公正な仮定ですか?


編集:私が求めている理由は、多くの場合、代わりにEXISTSを使用するようにINに基づいてSQLを書き換えることができ、またその逆も可能であり、一部のデータベースエンジンでは、クエリオプティマイザが2つを異なる方法で処理するためです。

例えば:

SELECT *
FROM Customers
WHERE EXISTS (
    SELECT *
    FROM Orders
    WHERE Orders.CustomerID = Customers.ID
)

次のように書き換えることができます。

SELECT *
FROM Customers
WHERE ID IN (
    SELECT CustomerID
    FROM Orders
)

または結合で:

SELECT Customers.*
FROM Customers
    INNER JOIN Orders ON Customers.ID = Orders.CustomerID

だから私の質問はまだ残っています、元のポスターはINとEXISTSが何をしているのか、そしてそれをどのように使用するのか疑問に思っていますか?


12
OPについてはわかりませんが、この質問への回答をお願いします!IDを返すサブクエリでINではなくEXISTSを使用する必要があるのはいつですか?
ロイティンカー、2010

8
ではJOIN、次のものが必要ですDISTINCT
Jaider

4
素晴らしいデモンストレーションですが、質問にはほとんど答えません
Junchen Liu

28
  1. EXISTSINサブクエリの結果が非常に大きい場合よりもはるかに高速です。サブクエリの結果が非常に小さい場合
    INよりも高速ですEXISTS

    CREATE TABLE t1 (id INT, title VARCHAR(20), someIntCol INT)
    GO
    CREATE TABLE t2 (id INT, t1Id INT, someData VARCHAR(20))
    GO
    
    INSERT INTO t1
    SELECT 1, 'title 1', 5 UNION ALL
    SELECT 2, 'title 2', 5 UNION ALL
    SELECT 3, 'title 3', 5 UNION ALL
    SELECT 4, 'title 4', 5 UNION ALL
    SELECT null, 'title 5', 5 UNION ALL
    SELECT null, 'title 6', 5
    
    INSERT INTO t2
    SELECT 1, 1, 'data 1' UNION ALL
    SELECT 2, 1, 'data 2' UNION ALL
    SELECT 3, 2, 'data 3' UNION ALL
    SELECT 4, 3, 'data 4' UNION ALL
    SELECT 5, 3, 'data 5' UNION ALL
    SELECT 6, 3, 'data 6' UNION ALL
    SELECT 7, 4, 'data 7' UNION ALL
    SELECT 8, null, 'data 8' UNION ALL
    SELECT 9, 6, 'data 9' UNION ALL
    SELECT 10, 6, 'data 10' UNION ALL
    SELECT 11, 8, 'data 11'
  2. クエリ1

    SELECT
    FROM    t1 
    WHERE   not  EXISTS (SELECT * FROM t2 WHERE t1.id = t2.t1id)

    クエリ2

    SELECT t1.* 
    FROM   t1 
    WHERE  t1.id not in (SELECT  t2.t1id FROM t2 )

    した場合t1、あなたのidはnull値を持ち、その後、クエリ1は、それらを見つけるだろうが、クエリ2は、ヌル・パラメータを見つける傾けます。

    私が意味するIN、それがnullのための結果を持っていないので、nullを使って何を比較することはできませんが、EXISTSヌルですべてを比較することができます。


この答えは、トム・カイトの感情(asktom.oracle.com/pls/asktom/…)のあらすじです
ジェロミーフランス語

この答えは直感に基づいていると思います。しかし、それは普遍的に真実であることはできません。たとえば、同等のSQLクエリを同じQUELクエリとして解析するIngresにはほぼ間違いなく当てはまりますが、同じものを複数の方法で作成する場合、SQLのahem-「豊富さ」が欠けています。
16

これらの2つのクエリは、t2.idが「NOT NULL」として定義されている場合に限り、論理的に同等です。テーブル定義に依存関係のない同値を付与するには、2番目のクエリは「SELECT t1。* FROM t1 WHERE t1.id not in(SELECT t2.id FROM t2 where t2.id is not null)」
DavidדודוMarkovitz

16

IN演算子を使用している場合、SQLエンジンは内部クエリからフェッチされたすべてのレコードをスキャンします。一方、を使用しているEXISTS場合、SQLエンジンは一致が見つかるとすぐにスキャンプロセスを停止します。


10

INは等価関係(またはNOTが前に付いている場合は不等価)のみをサポートします。= any / = someの
同義語です。例:

select    * 
from      t1 
where     x in (select x from t2)
;

EXISTSは、INを使用して表現できない関係のバリアントタイプをサポートします。例:-

select    * 
from      t1 
where     exists (select    null 
                  from      t2 
                  where     t2.x=t1.x 
                        and t2.y>t1.y 
                        and t2.z like '℅' || t1.z || '℅'
                  )
;

そして別のメモで-

EXISTSINのパフォーマンスと技術の違いは、特定のベンダーの実装/制限/バグが原因である可能性がありますが、多くの場合、データベースの内部を理解していないために作成された神話にすぎません。

テーブルの定義、統計の正確さ、データベース構成、およびオプティマイザのバージョンはすべて、実行計画に影響を及ぼし、したがってパフォーマンスメトリックに影響を与えます。


パフォーマンスに関するコメントに賛成票を投じてください。特定のDBMSに焦点を当てずに、最適なものを見つけるのはオプティマイザ次第であると想定する必要があります。
Manngo 2017年

9

Existsキーワードは、真または偽と評価が、IN対応するサブクエリ列内のすべての値を比較するキーワード。別のものSelect 1Existsコマンドで使用できます。例:

SELECT * FROM Temp1 where exists(select 1 from Temp2 where conditions...)

しかし、IN効率はそれほどExists速くありません。


5

おもう、

  • EXISTSクエリの結果を別のサブクエリと照合する必要がある場合です。Query#1の結果は、SubQueryの結果が一致する場所で取得する必要があります。結合の種類..たとえば、注文テーブル#2を注文した顧客テーブル#1を選択する

  • INは、特定の列の値がINリスト(1,2,3,4,5)にあるかどうかを取得します。例:次の郵便番号にある顧客を選択します。つまり、zip_code値は(....)リストにあります。

どちらを使用するか...適切に読み取れると感じたとき(意図をよりよく伝える)。


4

違いはここにあります:

select * 
from abcTable
where exists (select null)

上のクエリはすべてのレコードを返しますが、下のクエリは空を返します。

select *
from abcTable
where abcTable_ID in (select null)

試してみて、出力を観察してください。


1
うーん...エラー:[SQL0104]トークン)が無効でした。両方の場合において。特定のRDBMSを想定していますか?
jmarkmurphy 2017

3

私の知識によれば、サブクエリがNULL値を返すと、ステートメント全体がになりNULLます。その場合は、EXITSキーワードを使用しています。サブクエリの特定の値を比較したい場合は、INキーワードます。


3

どちらが高速かは、内部クエリによってフェッチされたクエリの数によって異なります。

  • 内部クエリが数千行をフェッチする場合は、EXISTの方が適しています
  • 内部クエリが数行をフェッチする場合、INはより高速になります

EXISTはtrueまたはfalseで評価しますが、INは複数の値を比較します。レコードが存在するかどうかわからない場合は、「存在」を選択する必要があります


3

その理由は、EXISTS演算子は「少なくとも見つかった」という原則に基づいて機能するためです。trueを返し、一致する行が少なくとも1つ見つかるとテーブルのスキャンを停止します。

一方、IN演算子をサブクエリと組み合わせる場合、MySQLは最初にサブクエリを処理し、次にサブクエリの結果を使用してクエリ全体を処理する必要があります。

一般的な経験則では、サブクエリに大量のデータが含まれている場合、EXISTS演算子を使用するとパフォーマンスが向上します。

ただし、サブクエリから返された結果セットが非常に小さい場合、IN演算子を使用するクエリはより高速に実行されます。


1

私が理解しているのは、NULL値を扱っていない限り、どちらも同じであるべきだということです。

クエリが= NULL vsの値を返さないのと同じ理由がNULLです。 http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/

ブール値とコンパレータの引数が行くように、ブール値を生成するには両方の値を比較する必要があり、それがif条件が機能する場合の動作です。そのため、INとEXISTSの動作の違いを理解できません。



0

サブクエリが複数の値を返す場合、条件で指定された列内の値がサブクエリの結果セットのいずれかの値と一致する場合は、外部クエリを実行する必要があります。このタスクを実行するには、inキーワードを使用する必要があります。

サブクエリを使用して、レコードのセットが存在するかどうかを確認できます。これにexistsは、サブクエリで句を使用する必要があります。existsキーワードは常に真または偽の値を返します。


0

これには簡単な答えがあると思います。システムでその機能を開発した人から確認してみませんか?

あなたがMS SQL開発者であるなら、ここに直接マイクロソフトからの答えがあります。

IN

指定した値がサブクエリまたはリストのいずれかの値と一致するかどうかを判断します。

EXISTS

行の存在をテストするサブクエリを指定します。



-1

EXISTSは、INよりもパフォーマンスが高速です。ほとんどのフィルター条件がサブクエリにある場合はINを使用し、ほとんどのフィルター条件がメインクエリにある場合はEXISTSを使用することをお勧めします。


その主張は本当に証拠に裏付けされていませんね?
Lukas Eder

-2

IN演算子を使用している場合、SQLエンジンは内部クエリからフェッチされたすべてのレコードをスキャンします。一方、EXISTSを使用している場合、SQLエンジンは一致が見つかるとすぐにスキャンプロセスを停止します。


@ジギーは説明?これは、受け入れられた回答でも述べられていることとほぼ同じです。「MUST」では、すべてのレコードを確認する必要があります。existは、1つだけを検出するとすぐに停止できます。
Ben Thurley、2014

いいえ、不正解です。INそして、EXISTS同等で互いに変換することができます。
Lukas Eder
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.