結合の使用による複数の表のデータの出力
問7
EMPLOYEE_IDとMANAGER_ID列の間には、親子関係があります。あなたは、EMPLOYEE_IDが105の従業員と上司が同じである従業員について、次のように社員番号と姓と上司IDを出力しようと考えています。目的の結果を得るためにはどの問い合わせを使用しますか。2つ選択しなさい。
EMPLOYEE_ID LAST_NAME MANAGER_ID ----------- --------------- ---------- 104 Ernst 103 105 Austin 103 106 Pataballa 103 107 Lorentz 103
-
a. SELECT employee_id,last_name,manager_id FROM employees
WHERE manager_id in (SELECT manager_id FROM employees WHERE employee_id = 105); -
b. SELECT E2.employee_id,E2.last_name,E2.manager_id
FROM employees E1
LEFT OUTER JOIN employees E2
ON E1.manager_id = E2.manager_id
WHERE E1.employee_id = 105; -
c. SELECT DISTINCT employee_id,last_name,manager_id FROM employees
WHERE employee_id = 105
UNION ALL
SELECT employee_id,last_name,manager_id FROM employees
WHERE manager_id in
(SELECT manager_id FROM employees WHERE employee_id = 105); -
d. SELECT E2.employee_id,E2.last_name,E2.manager_id
FROM employees E1
RIGHT OUTER JOIN employees E2
ON E1.manager_id = E2.manager_id
WHERE E1.employee_id = 105
AND E2.employee_id = 105;
自己結合の出題では多くの場合、従業員(EMPLOYEES)表が使用されるでしょう。ただし、上司と部下という関係だけでなく同僚という出題の仕方も考えられるので、結合条件に注意してください。
また、求めたい結果を得る方法は1つではありません。結合、副問合せ、集合演算子を用いても同じ結果を得ることができるので、頭を柔軟にしておきましょう。
選択肢aはシンプルだと思いますよ。「EMPLOYEE_IDが105の従業員の上司の番号」を副問合せにして、それと一致する社員を検索するのですから、次のとおり、設問が求める結果を得ることができます(選択肢aは正解)。
SQL> --選択肢a SQL> SELECT employee_id,last_name,manager_id FROM employees 2 WHERE manager_id in (SELECT manager_id FROM employees WHERE employee_id = 105); EMPLOYEE_ID LAST_NAME MANAGER_ID ----------- --------------- ---------- 104 Ernst 103 105 Austin 103 106 Pataballa 103 107 Lorentz 103
結合で求めるなら「EMPLOYEE_IDが105の従業員」の表(E1)と「EMPLOYEE_IDが105の従業員と上司の番号が同じ従業員」の表(E2)において結合できる行を検索すればいいですね。わざわざ外部結合にする必要はないと思いますが、本設問においてそこはこだわらなくてよいでしょう(選択肢bは正解)。
SQL> --選択肢b SQL> SELECT E2.employee_id,E2.last_name,E2.manager_id 2 FROM employees E1 3 LEFT OUTER JOIN employees E2 4 ON E1.manager_id = E2.manager_id 5 WHERE E1.employee_id = 105; EMPLOYEE_ID LAST_NAME MANAGER_ID ----------- --------------- ---------- 104 Ernst 103 105 Austin 103 106 Pataballa 103 107 Lorentz 103
選択肢cは、集合演算子がUNION
であれば正解だったのですが、UNION ALL
ではEMPLOYEE_IDが105の行が2件出力されるため、設問が求めている結果と同じにはなりません(正解は3つではなく、2つ選択しろと言っていますしね)。「最初の問い合わせにDISTINCT
が付いているので、EMPLOYEE_IDが105の行は重複しないのでは?」と考えた方は残念でした。DISTINCT
はSQL文全体にかかるのではなく、1つ1つのSELECT
に対して機能します。したがって、選択肢cは不正解です。
SQL> --選択肢c SQL> SELECT DISTINCT employee_id,last_name,manager_id FROM employees 2 WHERE employee_id = 105 3 UNION ALL 4 SELECT employee_id,last_name,manager_id FROM employees 5 WHERE manager_id in 6 (SELECT manager_id FROM employees WHERE employee_id = 105); EMPLOYEE_ID LAST_NAME MANAGER_ID ----------- --------------- ---------- 105 Austin 103 104 Ernst 103 105 Austin 103 106 Pataballa 103 107 Lorentz 103
選択肢bとよく似ていますが、外部結合がRIGHT
になっているのと、E2表の絞り込み条件(AND E2.employee_id = 105
)条件が追加されている点が異なります。この設問の場合、外部結合がLEFT
でもRIGHT
でも結果は変わりません。
しかし、E2表の絞り込み条件が追加されると、E1表との結合対象はEMPLOYEE_IDが105の行1件だけになってしまいますから、次のとおり、選択肢bとは結果は異なります(選択肢dは不正解)。
SQL> --選択肢d SQL> SELECT E2.employee_id,E2.last_name,E2.manager_id 2 FROM employees E1 3 RIGHT OUTER JOIN employees E2 4 ON E1.manager_id = E2.manager_id 5 WHERE E1.employee_id = 105 6 AND E2.employee_id = 105; EMPLOYEE_ID LAST_NAME MANAGER_ID ----------- --------------- ---------- 105 Austin 103
なお、結合、副問合せ、集合演算子のいずれを使っても同じ結果を求めることができるという場合もあるでしょう。実務では、実行速度やSQL文のメンテナンスしやすさなどを基準に、どの方法を決めるか検討するでしょうが、受験する段階では「こういう結果を求めたいんだけど」という問いに対して、いずれを使ってもSQL文が書けるようにしておいてください。