情報処理とは何から、データベースの基本的な話(情報処理試験のデータベーススペシャリスト程度の話まで)を書く、土日のシリーズ「Hello World程度のデータベース」です。
いま、SQLをやっています。
SQLは検索(select)、挿入(insert)、削除(delete)、更新(update)とあって、今回はSELECTにおける副問い合わせです。
■副問い合わせとは
いままで、WHERE句には、値を使っていましたが、検索結果を使うことも出来ます。
たとえば、ここで、
前回同様SHAIN_TBLが
そしてSYUSSEKI_TBLがこんなかんじ
になっているとき、(まったく意味ないんですけど)
SYUSSEKI_TBLでSHAINIDが、2番の人の姓と名をSHAIN_TBLから検索して出す場合、
SELECT SHAIN_TBL.SEI, SHAIN_TBL.MEI FROM SHAIN_TBL WHERE (SHAIN_TBL.SHAINID= (SELECT SHAINID FROM SYUSSEKI_TBL WHERE SYUSSEKI_TBL.SHAINID = 2)); |
となります。
あるテーブルの検索結果(カッコ内のSELECT)と、
テーブルの値(SHAIN_TBL.SHAINID)を
比較したいときに、
上記のように書きます。このとき”カッコ内のSELECT”が、副問い合わせ(サブクエリー)になります
■このサブクエリでは1つのレコードしか返せません
では、もうちょっと意味のあるものをやりましょう。
SYUSSEKI_TBLでEVENTIDが123番の人のSHAIN_TBLの姓と名をだしてみましょう。
つまり、イベント番号123番の出席者ということです。
これは、さっきのSHAINID=2がEVENTID=123に変わっただけだからと考えて
SELECT SHAIN_TBL.SEI, SHAIN_TBL.MEI FROM SHAIN_TBL WHERE SHAIN_TBL.SHAINID=(SELECT SHAINID FROM SYUSSEKI_TBL WHERE SYUSSEKI_TBL.EVENTID = 123) |
と書いてしまうと、Accessでこうやると、
このサブクエリでは1つのレコードしか返せません
というエラーになります。
どこが違うのでしょう。どーしてエラーになるのでしょう。
■INとNOT IN
はじめのSHAINID=2のほうは、結果を満たすレコードが1レコードしかありません。
それに反して、2番目のEVENTID=123のほうは、結果を満たすレコードが複数(3レコード)あります。=で結ばれたとき、複数だとこまります。
初めの意図のようにイベント番号が123のもののレコードを出したい場合は、INを使います。こんなかんじ
SELECT [SHAIN_TBL].[SEI], [SHAIN_TBL].[MEI] FROM SHAIN_TBL WHERE (((SHAIN_TBL.SHAINID) IN (SELECT SHAINID FROM SYUSSEKI_TBL WHERE SYUSSEKI_TBL.EVENTID = 123))); |
この場合、副問い合わせの中に「あるもの」になりますけど、逆に、「ないもの」を出したい場合はINの代わりに、NOT IN と書きます。
■EXISTS
同じことを、EXISTSを使っても書けます。
こんなかんじ
SELECT [SHAIN_TBL].[SEI], [SHAIN_TBL].[MEI] FROM SHAIN_TBL WHERE EXISTS ( SELECT * FROM SYUSSEKI_TBL WHERE [SHAIN_TBL].[SHAINID]=[SYUSSEKI_TBL].[SHAINID] AND SYUSSEKI_TBL.EVENTID=123); |
WHERE句の後にEXISTS句を書いて、そのあとの副問い合わせに連結内容(SHAINIDが一致)と条件(EVENTIDが123)と書けばいいのですが。。
うーん、こっちのほうがわかりにくいですね。
これにもNOT EXISTSがあります(存在しないものを選ぶ)
■限定述語ALLとANY(SOME)
ALLとANY(SOMEと同じ)というのがあります。
ALLと書くと、副問い合わせの結果すべてに対して、条件を満たすものということになります。
あんまり意味ないですけど、イベント番号123の出席者すべての社員番号より大きい社員番号の人を出すには、
SELECT [SHAIN_TBL].[SEI], [SHAIN_TBL].[MEI] FROM SHAIN_TBL WHERE SHAIN_TBL.SHAINID > ALL(SELECT SYUSSEKI_TBL.SHAINID FROM SYUSSEKI_TBL WHERE SYUSSEKI_TBL.EVENTID=123); |
というようにかきます。
WHERE句のところ、ALLを使って書くと、
まず、副問い合わせの結果は1,2,3となるので、それより大きい、4番の香坂さんが表示されます(1件だけ)
またまたあんまり意味ないですけど、イベント番号123の出席者のだれか1人の社員番号より大きい社員番号の人を出すには、
SELECT [SHAIN_TBL].[SEI], [SHAIN_TBL].[MEI] FROM SHAIN_TBL WHERE SHAIN_TBL.SHAINID > ANY(SELECT SYUSSEKI_TBL.SHAINID FROM SYUSSEKI_TBL WHERE SYUSSEKI_TBL.EVENTID=123); |
というようにかきます。
副問い合わせの結果は前回同様1,2,3なんですけど、そのうち、どれか1つより大きければよいとなると、2番の小笠原さんは、1番より大きいのでOK、4番の香坂さんは、どれよりも大きいのでOK,でも、1番の吉村さんは、1,2,3どれよりも大きくない(1番とは同じ、2,3より小さい)のでNG,ということで、2番の小笠原さんと、4番の香坂さんが表示されます。
っていうかんじなんですけど、わかりましたあ??