回答:
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
使用した場合でも計画を調整できます。
select * from [table] where [field] in (select [field] from [table2])
と同じ結果(およびクエリプラン)を返しますselect * from [table] join [table2] on [table2].[field] = [table].[field]
。
table
返し、2番目のクエリはtable
and からすべてを返しますtable2
。一部の(ほとんど古い)SQLデータベースでは、in
クエリはネストされた結合として実装されjoin
ますが、クエリはネスト、マージ、ハッシュ化など、最も高速な方法で実行できます。
exists
彼らは道もすなわちその便利なことができるので、ケースステートメント内で使用することができますselect case when exists (select 1 from emp where salary > 1000) then 1 else 0 end as sal_over_1000
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)
ルールオプティマイザーに基づく:
EXISTS
IN
サブクエリの結果が非常に大きい場合、はよりもはるかに高速です。IN
EXISTS
サブクエリの結果が非常に小さい場合、はより高速です。コストオプティマイザーに基づく:
私はあなたがそれらが何をしているのかを知っていると想定しているため、異なる方法で使用されているので、私はあなたの質問を次のように理解します: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が何をしているのか、そしてそれをどのように使用するのか疑問に思っていますか?
JOIN
、次のものが必要ですDISTINCT
EXISTS
IN
サブクエリの結果が非常に大きい場合よりもはるかに高速です。サブクエリの結果が非常に小さい場合
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'
クエリ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
ヌルですべてを比較することができます。
IN
演算子を使用している場合、SQLエンジンは内部クエリからフェッチされたすべてのレコードをスキャンします。一方、を使用しているEXISTS
場合、SQLエンジンは一致が見つかるとすぐにスキャンプロセスを停止します。
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 || '℅'
)
;
EXISTSとINのパフォーマンスと技術の違いは、特定のベンダーの実装/制限/バグが原因である可能性がありますが、多くの場合、データベースの内部を理解していないために作成された神話にすぎません。
テーブルの定義、統計の正確さ、データベース構成、およびオプティマイザのバージョンはすべて、実行計画に影響を及ぼし、したがってパフォーマンスメトリックに影響を与えます。
違いはここにあります:
select *
from abcTable
where exists (select null)
上のクエリはすべてのレコードを返しますが、下のクエリは空を返します。
select *
from abcTable
where abcTable_ID in (select null)
試してみて、出力を観察してください。
どちらが高速かは、内部クエリによってフェッチされたクエリの数によって異なります。
EXISTはtrueまたはfalseで評価しますが、INは複数の値を比較します。レコードが存在するかどうかわからない場合は、「存在」を選択する必要があります
その理由は、EXISTS演算子は「少なくとも見つかった」という原則に基づいて機能するためです。trueを返し、一致する行が少なくとも1つ見つかるとテーブルのスキャンを停止します。
一方、IN演算子をサブクエリと組み合わせる場合、MySQLは最初にサブクエリを処理し、次にサブクエリの結果を使用してクエリ全体を処理する必要があります。
一般的な経験則では、サブクエリに大量のデータが含まれている場合、EXISTS演算子を使用するとパフォーマンスが向上します。
ただし、サブクエリから返された結果セットが非常に小さい場合、IN演算子を使用するクエリはより高速に実行されます。
私が理解しているのは、NULL値を扱っていない限り、どちらも同じであるべきだということです。
クエリが= NULL vsの値を返さないのと同じ理由がNULLです。 http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/
ブール値とコンパレータの引数が行くように、ブール値を生成するには両方の値を比較する必要があり、それがif条件が機能する場合の動作です。そのため、INとEXISTSの動作の違いを理解できません。
In certain circumstances, it is better to use IN rather than EXISTS. In general, if the selective predicate is in the subquery, then use IN. If the selective predicate is in the parent query, then use EXISTS.
https://docs.oracle.com/cd/B19306_01/server.102/b14211/sql_1016.htm#i28403
私は、EXISTSキーワードの使用がしばしば非常に遅いことを発見しました(これはMicrosoft Accessでは非常に当てはまります)。代わりに、この方法で結合演算子を使用します: should-i-use-the-keyword-exists-in-sql
EXISTSは、INよりもパフォーマンスが高速です。ほとんどのフィルター条件がサブクエリにある場合はINを使用し、ほとんどのフィルター条件がメインクエリにある場合はEXISTSを使用することをお勧めします。
IN演算子を使用している場合、SQLエンジンは内部クエリからフェッチされたすべてのレコードをスキャンします。一方、EXISTSを使用している場合、SQLエンジンは一致が見つかるとすぐにスキャンプロセスを停止します。
IN
そして、EXISTS
同等で互いに変換することができます。
JOIN
代わりとして使用できる部分IN
。