SQL攻略 - Web上でSQLを実行しながらマスターするサイト
ホーム >> SQL攻略 - 入れ子の問合せ

入れ子の問合せ

午後問題によく出題される入れ子の問合せについて解説します。

1.副問い合わせ

--最小の部署番号に所属する従業員の抽出
SELECT*
FROMEMP
WHEREEMP.DEPTNO = (
SELECT MIN(DEPT.DEPTNO)
FROM DEPT)

WHEREのあとのEMP.DEPTNOと、別のSELECT文の問合せ結果との比較をしています。このような問合せを副問合せといいます。

カッコ内側のSELECT MIN(DEPT.DEPTNO) FROM DEPT)で抽出された、MIN(DEPT.DEPTNO)とEMP.DEPTNOを比較し、等しいレコードを抽出します。

この場合、内側のSELECT文の後に書かれてある項目(ここではMIN(DEPT.DEPTNO) )は、EMP.DEPTNOと比較可能なものである必要があります。

例えば、内側の問合せがSELECT DEPT.DEPTNO FROM DEPTだと、複数のレコードを返してくるので、エラーになります。


2.IN記述

--基本的なINの使い方
SELECT*
FROMEMP
WHEREDEPTNO IN (10,30)

INを使用すると()に囲まれているものを含むレコードを抽出できます。
上記の例だと、DEPTNO = 10 OR DEPTNO = 30 と同じ意味になります。
否定をする場合はNOT IN のようにINの直前にNOTを付けます。

それでは実習です。2題出題します。

--入れ子の問合せでのINの使い方
SELECT*
FROMEMP
WHEREDEPTNO IN (SELECT DEPTNO FROM DEPT WHERE DNAME LIKE '%S%')

入れ子の問合せは、()の中がSQLのSELECT文に変わるだけです。内側のSQLが実行され(20,30,40)が抽出されIN (20,30,40)が実行されます。

ソフトウェア開発技術者午前平成15年問73
次の SQL 文によって,“社員の居室”表及び“部屋の管理部門”表から新たに得られる表はどれか。
社員の居室
社員番号社員名部門居室番号
001田中A1110
002鈴木A1111
003佐藤A1203
004福田A2201
005渡辺A2202

部屋の管理部門
部屋番号部門
110A1
111A1
201A2
202A2
203A2

SELECT社員名
FROM社員の居室
WHERE居室番号 NOT IN (
SELECT部屋番号
FROM部屋の管理部門
WHERE部門 = 'A1'
)


社員名
田中
鈴木

社員名
福田
渡辺

社員名
田中
鈴木
佐藤

社員名
佐藤
福田
渡辺
正解



解説

1.副問い合わせの実行結果を確認する
WHERE 部門 = 'A1' ですから110と111が返されます。

2.NOT IN (110,111)の実行結果をさがす。
以上よりエが正解となります。

3.EXISTS記述

--給料がもっとも高い従業員の抽出
SELECTENAME,SAL
FROMEMP EA
WHERENOT EXISTS(
SELECT * FROM EMP EB
WHRE EB.SAL > EA.SAL
)

このSQLはEXISTS記述を使って、給料が最も高い従業員の抽出を行っています。

EXISTS記述は()の中に書いてあるSQLで抽出されるレコードがある場合は真、無い場合は偽を返してきます。真のときのみ外側のWHERE条件が成立し、レコードが抽出されます。

実際の動作は外側のEMP表(EA)から一行ずつ取り出され、内側のSQLで比較されます。

EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7369 SMITH CLERK 7902 1980-12-17 800 20
7499 ALLEN SALESMAN 7698 1981-02-20 1600 300 30
7521 WARD SALESMAN 7698 1981-02-22 1250 500 30
7566 JONES MANAGER 7839 1981-04-02 2975 20
7654 MARTIN SALESMAN 7698 1981-09-28 1250 1400 30
7698 BLAKE MANAGER 7839 1981-05-01 2850 30
7782 CLARK MANAGER 7839 1981-06-09 2450 10
7839 KING PRESIDENT 1981-11-17 5000 10
7844 TURNER SALESMAN 7698 1981-09-08 1500 0 30
7900 JAMES CLERK 7698 1981-12-03 950 30
7902 FORD ANALYST 7566 1981-12-03 3000 20
7934 MILLER CLERK 7782 1982-01-23 1300 10

EMP表のEA側の一行(SMITHの給料の800)が取り出されます。これを用いて内側のSQLでEB.SAL > EA.SALの比較が行われます。EA.SALは800なので内側のSQLはレコードを返し、EXISTSは真となります。NOTで否定しているので、答えは偽となり、SMITHのレコードは抽出されません。

上から順番にデータが取り出され、KINGの行までくると、KINGのSALは5000ですから、内側のSQLはレコードを抽出しないので、EXISTSは偽となり、NOTで真になるので、KINGのレコードは抽出されます。

これで [ 入れ子の問合せ ] は終了です。