SQLのINとEXISTSの違い、相関問合せと相関副問合せの違いについて

このQ&Aのポイント
  • SQLのINとEXISTSは、条件式で複数の値を比較する際に使用されるが、その使い方には違いがある。INは特定の項目が、サブクエリの結果に含まれているかどうかを確認するために使用される。一方、EXISTSはサブクエリの結果が空でないかどうかを確認するために使用される。
  • 相関問合せは、副問合せ文中で主問合せの表を参照することを指す。ただし、相関問合せはEXISTSの場合にのみ使用することができる。一方、INを使用している場合でも相関問合せは使われることがある。これにより、主問合せと副問合せが関連付けられ、特定の条件が満たされる場合にのみ結果を返すことができる。
  • 相関副問合せは、相関問合せと同じように、副問合せ文中で主問合せの表を参照することを意味する。しかし、相関問合せと異なり、相関副問合せは副問合せが主問合せに関連するフィルタリング処理を行うために使用される。つまり、相関副問合せは副問合せの結果を条件に基づいてフィルタリングすることができる。相関副問合せは、相関問合せの一部として使用されることもある。
回答を見る
  • ベストアンサー

SQLの質問

3つわからないことがあります。 1.SQLのINとEXISTSって何が違うんですか? 本を見ると ・WHERE 項目 IN(select・・・) ・WHERE EXISTS(select・・・) INはWHEREとの間に何か入り、EXISTSは何も入ってないようですが・・。違いがわかりません。 2.そして、上の質問の続きですが、副問合せ文中で主問合せの表を参照する ことを相関問合せと、いうらしいのですが、解説を見ると、existsのときの み相関問合せは使える、ように書いてあります。しかし別の本ではINを使用 してるときでもこの相関問合せが使われていて・・・・・??何がなん だかわからなくなりました。 3.そしてまた別の本では、”相関副問合せ”というものがあり、相関問合せと同じ ものなのか、違うものなのかわかりません。ぱっと見た限りでは相関問合せと同じに見えるのですが・・・

  • laoff
  • お礼率28% (2/7)

質問者が選んだベストアンサー

  • ベストアンサー
  • RAPTsong
  • ベストアンサー率42% (74/175)
回答No.2

> ある資料によると テーブル名とキー名を読み替えてみればわかることですが、 ご提示のコードは、私が既に提示したサンプルコードと全く同一です。 > select Aコード from 品物 > where exists (select Aコード from 明細 >           where 品物.Aコード=明細.Aコード) ここで、副問い合わせの「select Aコード」の「Aコード」は、 別に「Aコード」である必要はなく、「*」でも「'x'」でも何でも良いです。 exists は、その副問い合わせの結果が真(有効行がある)か偽(有効行が無い) かで判断します。 > select Aコード from 品物 > where exists (select Aコード from 明細 >           where 品物.Aコード=明細.Aコード) 1.(品物)ある1行を選択 2.(明細)1で選択した行の品物.Aコードが、明細.Aコードと一致するものがあれば真となり1の行は選択される。 ここで、一致しなければ結果は偽となるため、1の行は選択されない。 3.すべての品物テーブルの行について1~2を繰り返す。 > select Aコード from 品物 > where Aコード in (select Aコード from 明細) 1.(明細)明細テーブルから明細.Aコードをすべて選択。 2.(品物)品物.Aコードが1で選択された明細.Aコードと一致するものがあればその行を選択。 ここで、一致しなければその行は選択されない。 結果的に、いずれも、品物テーブルと明細テーブルで、両方に同一のAコードが存在する Aコードが選択されます。 [0#: も] っとも、今回のような単純なケースであれば、下記のように結合を使ったほうが速いですが。。 select 品物.Aコード from 品物, 明細 where 品物.Aコード = 明細.Aコード

その他の回答 (1)

  • RAPTsong
  • ベストアンサー率42% (74/175)
回答No.1

select * from foo_tbl where key1 in (100,200,300); これは、下記のSQL文と同等です。 select * from foo_tbl where key1 = 100 or key1 = 200 or key1 = 300; select * from foo_tbl where exists (select key1 ftom baz_tbl where key1 = 200) このSQL文は、baz_tblテーブルのkey1が200である行が存在した場合、 foo_tblのすべての列を返します。 すなわち、in は選択された列のいずれかと一致した場合にその行が 選択されますが、existsの場合は、()内で選択された行が1つでもあれば 主問い合わせ側の行は有効となります。 相関は、 select * from A where exists (select 'x' from B where A.PK = B.PK) などのように使用します。 上記SQL文は下記のように書き換える事も可能です。 select * from A where PK in (select PK from B) ちなみに、相関副問い合わせは、やってみたら分かることですが、 INでもEXISTSでも使用可能です。 > ”相関副問合せ”というものがあり、相関問合せと同じものなのか 同じコトでしょう。そもそも、「相関」は副問い合わせ以外では 発生しようがないので。

laoff
質問者

お礼

回答ありがとうございます。ほとんど理解できました。 ただINとEXSITSの違いがなんとなく・・・。言われて見れば そうだなぁと思うのですがイメージがつきませんでした。 ある資料によると、 select Aコード from 品物 where exists (select Aコード from 明細           where 品物.Aコード=明細.Aコード) はINを使うと select Aコード from 品物 where Aコード in (select Aコード from 明細) と書き換えることができるそうです。 この二つは実際は どのように検索して結果を表示するのか、もう一度ご説明お願いしたいのですが・・・。           

関連するQ&A

  • SQLの副問い合わせと相関副問い合わせの違い

    只今シスアド勉強中なのですが、SQLのところでつまずいてしまっています。副問い合わせと相関副問い合わせのそれぞれの意味はわかるのですが、SQL文を判断する時、副問い合わせと相関の副問い合わせというのを一目で判断するコツを教えていただけないでしょうか? それとEXISTSを使った場合の副問合せと相関副問い合わせでも混乱しています。副問合せの場合はサブクエリーから先に条件をクリアしていくと思いますが、EXISTSの場合は真が偽しかデータを返しませんよね? 例えばEXISTS(SELECT * FROM 売上明細 WHERE 売上明細.商品CD=商品表.商品CD)とあった時、 1つでも商品CDが一致しているものがあれば真のみを返す。 でも、これが相関副問い合わせであれば親分に対して真の”データ”を返す?この場合の副問合せと相関副問い合わせの違いってSQL分のどの部分で判断するのでしょうか?わかりにくい説明でもうしわけありません。お分かりになる方どうぞアドバイス下さい。

  • sqlについて

    SQLについて質問です。 VBからMDBにSQLでデータの参照をしたいのですが ("select * from abc where No = " & No & " ;") テーブル内の数ある項目の中で一つだけまたは複数除いて参照する場合のSQL文を教えてください。 項目が60個ほどありますので一つ一つ指定していくとすごく長いSQLになってしまいそうですのでお知恵をお貸しください><

  • SQL文について質問させて頂きます。

    いつもお世話になっております。いろいろSQL文の本を読んだのですがわからないので今回もよろしく お願い致します。 SELECT DISTINCT * FROM bukken WHERE (id IN (SELECT fid FROM fudou_kodawari WHERE kid IN (1,4))) というSQL文があるのですが、これだと1,4が1つでも含まれるリストが出てくるのですが1,4が完全に一致しないと出てこないようにするにはどのようにSQL文を変更すれば良いのでしょうか? 何卒よろしくお願い致します。

  • SQLの高速化の方法について

    自分ではすぐに浮かばないのですが、結構急ぎのことなのでお時間がある方でご存知の方がいらしたら教えて下さると嬉しいです。なので、途中で解決していたり質問を途中で消しているかもしれませんがよろしくお願いします。 SQLで自分が書いた文を高速化したいのですが、一般的にこうすると遅いからこうする方が良いというのがあれば教えてください。 一応自分でも調べててWHERE句では結合よりも先に条件を記載する方が良いとか書いてました。 あと、IN演算子がちょっと問題な演算子ということが。 確かにSQL文を書いているソースではいくつかSELECT文があって、それぞれでIN演算子を使っています。 調べてるとIN演算子をEXISTS演算子に書き換える方が良くなるとあったのですがEXISTS演算子はカッコ内で再度SELECT文を作るんですよね? 今使っているIN演算子では、ほぼカッコ内に数字のいくつかの候補があってそこから該当する数字を選ばれるという形の方。 WHERE AAA IN ('122','244','366') といった形です。 あるSELECT文でIN演算子を使って絞った値データを次のSELECT分のIN演算子の値候補として使用しています。 つまり、上記のような文122と244のデータが見つかってSELECTされると次のSELECT文のIN演算子の候補として122と244が入るという形です。 ちなみにこの処理のメインとなるテーブルでは一つの項目の値を木構造で分けているのでその辺りも考えないといけません。 以前、こちらのサイトで教えて貰った方法で動いている GROUP BY AA.A1 HAVING COUNT(*) >= 0 といった処理も重くしてしまうのでしょうか?

    • ベストアンサー
    • MySQL
  • 埋め込みSQLについて

    現在C言語で開発を行っている初級のIT技術者です。 pro*cでは、inner joinやexistsを使うとコンパイルエラーとなってしまいます。 泣く泣く、inを使ってしまいました。例えば以下テーブルがあります。 請求テーブル 識別ID 更新日付 201405 20140922 100177 20140204 258087 20140412 201497 20140711 258055 20140812 履歴テーブル 加入者ID 識別ID(主キー) 2014   201405 5800   587405 2014   258087  8507   874575 以下をパッケージに記載しています。 EXEC SQL SELECT 色々 FROM 請求テーブル WHERE 識別ID IN (SELECT 識別ID FROM 請求テーブル WHERE 加入者ID = 変数) ORDER BY 更新日付 ASC 例えば、変数として2014が来た場合は、履歴テーブルより 2014   201405 2014   258087 が選択されて、請求テーブルの更新日付を見て古い方を取ってくるので 結局258087 20140412が取得されます。この代わりとなる、pro*cで記述できる SQLはどんなのがありますでしょうか?

  • 相関副問い合わせについて

    いつもお世話になっています。 相関副問い合わせについて質問です。テーブルSalesに三つのカラム、ProductID、QuantityとSaleDateがあるとします。 各商品の日ごとの売上数量が商品毎の平均の売上数量より上の日を取り出すSQL文がSQL1のようになるようです。ここでわからないのがSQLの動きです。AVG関数は集合関数だと思うのですが、副問い合わせにGROUP BY句がないけど、相関によりそれが成り立っているというのはそういう動きなんだなと理解しました。 ただ自分のこれまでの経験では、こういったものをやったことがないので、基本的に副問い合わせが先に評価され、その結果と主SQLのWHERE句で比較をして主SQLが評価されるという基本的な動きが普通という考え方がこびりついています。 この相関副問い合わせのSQL1だとテーブルs1がProductID毎に評価され、ProductIDが移り変わると副問い合わせのテーブルs2でそのs1.ProductIDと同じ値毎に平均が計算されていくという動きをしているととらえているのですが、それであっているのでしょうか? よろしくおねがいします。 (SQL1) SELECT s1.SaleDate FROM Sales AS s1 WHERE s1.Quantity > (SELECT AVG(s2.Quantity) FROM Sales AS s2 WHERE s1.ProductID = s2.ProductID )

  • SQL文の副問い合わせについて

    SQLの勉強をし始めて間もありませんが、以下のSQLについて教えてください。 実はこの問題は昭晃堂発行の北川博之先生が書いた「データベースシステム」という本に乗っている問題です。以下のようなデータベースがあります。 部門(_部門番号,部門名) 部品(_部品番号,部品名) 業者(_業者番号,業者名,住所,電話番号) 従業員(_従業員番号,従業員名,氏名,住所,年齢) 供給(_部門番号,_部品番号,_業者番号,単価,数量) _がついているのは主キー この中で、登録されているすべての部品の供給を受けている部門の部門番号を表示するSQLを記せという問題があります。 つまり、部品表の供給テーブルの中の部門番号ごとに、供給テーブルのなかに含まれる部品番号と部品テーブルの部品番号がすべて一致するかを調べるSQLを書かなければならないということです。 まったく歯が立たないので、いろいろと調べた結果、 SELECT DISTINCT 部門番号 FROM 供給 AS 供給1 WHERE NOT EXISTS( SELECT * FROM 部品 WHERE NOT EXISTS( SELECT * FROM 供給 AS 供給2 WHERE 部品.部品番号=供給2.部品番号 AND 供給1.部門番号=供給2.部門番号 )); が正解であるということでした。 しかし、NOT EXISTSが2回も出てくるばかりか、副問い合わせの連続で頭が混乱してよく理解できません。 このSQL文について、具体的にはどのようなことをやっているのでしょうか?教えてください。お願いします。

  • 【初歩的な質問ですが・・・】 SQL文書き方がわかりません

    SQLの知識に乏しい者です。 よろしくお願い致します。 ●テーブルA ・会計コード ・年度 ・部署番号 ・社員番号 ・その他幾つかのデータ ※Where句で「年度>2002年」以降を抽出 のテーブルがあります。 この時、Bテーブルで ●テーブルB ・会計コード(主キー) ・年度 ・部署番号(主キー) ・社員番号(主キー) ・その他幾つかのデータ ※Aテーブルで抽出されたデータの中から絞り込む というテーブルを抽出するSQL文を組みたいのですが、効率の良いやり方がわかりません。 副問合せで  Select [B表で抽出した列名…]  From B表  Where 会計コード = (Select 会計コード               From A表               Where 年度 > '2002')  AND 部署番号 = (Select 部署番号             From A表               Where 年度 > '2002') ・・・・以下省略 の様に書くと効率が悪い気がしました。 (実際には、副問合せが6個書くことになるため) 良い書き方を知っている方がいらっしゃいましたら、よろしくお願い致します。

  • sql: update またはinsert を判断して1回で実行するには

    わかりやすいように単純にしていますが table1に ID と titleフィールドがあるとして、 update table1 set title = 'no1' where ID = '1' と insert into table1 (ID,title) values ('1','no1') これを一個にまとめたいのですが、 一回のSQLで 指定したIDが なければ、挿入、存在すれば、アップデート みたいな処理は可能でしょうか? CASEとかEXISTS とかの組み合わせでできますでしょうか? 最近まで、SQLを利用したデータベースほとんど 利用していなかったので 初歩的なことで申し訳わけありませんが インターネットの解説サイトをみてもわからないので SQLの本を購入しましたが届くのが来週以降なので もし できるのでしたら、 使う関数名だけでもいいので教えてください。

  • SQL分のコツ

    INTERBASEを利用しているのですが、あるバッチ処理用のSQLが膨大にCPUを消費してしまい、ほかのプロセスに影響を与えています。 1文で3つのテーブルを参照しつつ、MAXを4項目、副問い合わせも2か所しているので、負荷がかかるのはわかっているのですが。。。 SQLの構文の書き方でパフォーマンスを向上させるテクニックがあればお教え下さい。