ホームページ >データベース >mysql チュートリアル >mysqlでinの代わりに何を使用するか
Mysql では、in の代わりにexists が使用されます。exists はループを使用して外部テーブルを 1 つずつクエリします。各クエリは、exists の条件文をチェックします。exists の条件文がレコード行を返すことができる場合、条件が true の場合、現在の状態が返され、このレコードにループします。
このチュートリアルの動作環境: Windows7 システム、mysql8 バージョン、Dell G3 コンピューター。
exists は、ループを使用して外部テーブルを 1 つずつクエリします。各クエリは、exists の条件ステートメントをチェックします。exists の条件ステートメントは、レコード行を返すことができます (レコード行の数に関係なく、返せる限り)、条件は true の場合、現在のループ内のレコードが返されます。それ以外の場合、exists の条件文がレコード行を返せない場合、現在のループ内のレコードは破棄されます。存在するはブール条件のようなもので、結果セットが返せる場合は true、返せない場合は false
次のように:
select * from user where exists (select 1);
ユーザーの記録サブ条件の select 1 は常にレコード行を返すことができるので、ユーザーテーブルのすべてのレコードが結果セットに追加されるため、select * from user;
と同じになります。そして次のように
select * from user where exists (select * from user where userId = 0);
user テーブルをループするときに、条件ステートメント (select * from user where userId = 0) をチェックすることがわかります。userId が 0 になることはないため、条件ステートメントは常に返されます。空のセットであり、条件は常に false になります。その場合、ユーザー テーブル内のすべてのレコードは破棄されます。
not selected は、exists の反対であり、また、exists 条件が結果セットを返す場合、ループされたレコードは破棄され、それ以外の場合はループされたレコードが結果セットに追加されます。
一般に、テーブル A に n 個のレコードがある場合、存在するクエリは、これらの n 個のレコードを 1 つずつ取り出して、存在する条件を n 回判定する
in query は、複数の or 条件を重ね合わせたものと同等で、次のようなクエリ
select * from user where userId in (1, 2, 3);
と同等です。
select * from user where userId = 1 or userId = 2 or userId = 3;
not in は、次のように in の逆です。
select * from user where userId not in (1, 2, 3);
select * from user where userId != 1 and userId != 2 and userId != 3;
と同等です。一般に、in クエリでは、最初にサブクエリ条件を結合します。結果セットが B で、合計 m 個のレコードがあると仮定します。次に、サブクエリ条件の結果セットが m に分解され、m 個のクエリが実行されます。
クエリ内 サブ条件の返される結果には、
select * from user where userId in (select id from B);
ではなく
select * from user where userId in (select id, age from B);
などのフィールドが 1 つだけ含まれている必要があります。ただし、exists にはこの制限はありません。 exists と in のパフォーマンスを考えてみましょう。
次の SQL ステートメントを考えてみましょう
1: select * from A where names (select * from B where B.id = A.id);
2: select * from A where A.id in (select id from B);
Query 1. 理解しやすいように、次の疑似コードを変換できます。
for ($i = 0; $i < count(A); $i++) { $a = get_record(A, $i); #从A表逐条获取记录 if (B.id = $a[id]) #如果子条件成立 $result[] = $a; } return $result;
Thisおそらくそれが意味することでしょう。実際、クエリ 1 は主にテーブル B のインデックスが使用されていることがわかります。テーブル A がクエリの効率にほとんど影響を与えない方法
テーブルのすべての ID が使用されていると仮定します。 B は 1,2,3, クエリ 2 は
select * from A where A.id = 1 or A.id = 2 or A.id = 3;
これに変換できます わかりやすいです。ここでは主に A のインデックスが使用されます。テーブル B がクエリにほとんど影響を与えない仕組み
not 存在と not in
1 を見てみましょう。
select * from A where not存在 (select * from B where B.id = A.id); #2.
select * from A where A.id not in (select id from B);
クエリ 1 を見ると、B のインデックスを使用している点は上記と同じです
select * from A where A.id != 1 and A.id != 2 and A.id != 3;に変換できます。not in は Range クエリであることがわかります。この != range クエリはインデックスを使用できません。つまり、それぞれのクエリはインデックスを使用できません。レコードがテーブル B に存在するかどうかを確認するには、テーブル A のレコードをテーブル B で 1 回走査する必要があります。したがって、存在しない方が、存在しないよりも効率的です。mysql の in ステートメントは、次の間のハッシュ接続です。外部テーブルと内部テーブルですが、exists ステートメントは外部テーブルのループであり、ループがループするたびに内部テーブルがクエリされます。 in ステートメントよりも存在する方が効率的であると誰もが常に信じてきましたが、このステートメントは実際には不正確です。これは環境によって異なります。
クエリされる 2 つのテーブルが同じサイズの場合、in とexists
2 つのテーブルのうちの 1 つが小さく、もう 1 つが大きいテーブルの場合は、大きいサブクエリ テーブルには存在を使用し、小さいサブクエリ テーブルには in を使用します。
例: テーブル A (小さい) table )、テーブル B (大きなテーブル) 1: select * from A where cc in (select cc from B) は非効率的であり、テーブル A の cc 列のインデックスを使用します。 select * from A where names(select cc from B where cc=A.cc) は効率的で、テーブル B の cc 列のインデックスを使用します。 反対の2:select * from B ここで、cc in (select cc from A)は非常に効率的で、テーブルBのcc列のインデックスを使用します。 select * from B where names(select cc from A where cc=B.cc) は非効率であり、テーブル A の cc 列のインデックスを使用します。 not in および notexisting クエリ ステートメントで not in を使用する場合、インデックスを使用せずに内部テーブルと外部テーブルの両方でテーブル全体がスキャンされ、not extsts のサブクエリは引き続きインデックスを使用できます。テーブル。したがって、どのテーブルが大きくても、notexists を使用した方が not in
よりも高速です。in と = の違い
select name from students where name in ('zhang','wang','li','zhao'); 与select name from students where name='zhang' or name='li' or name='wang' or name='zhao' 結果は同じです。推奨チュートリアル: mysql ビデオ チュートリアル
以上がmysqlでinの代わりに何を使用するかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。