助け合いフォーラム

Oracle DB

Oracle Master 12c Bronze SQL基礎(1Z0-061)
問題ID : 13683
問題を開く
EMPLOYEES表の構造を確認して下さい。



給与の額が所属する部署の最低給与を超える従業員の一覧と、部署ごとの最低給与を表示します。
以下の問合せを実行しましたが、実行結果について正しい記述はどれですか。

 SELECT e.employee_name, e.salary, e.department_id, s.minsal
 FROM employees e, (SELECT department_id, MIN(salary) minsal FROM employees GROUP BY department_id) s
 WHERE e.salary > s.minsal
 ORDER BY e.department_id, e.salary;

正解

実行されるが正しい結果が返されない

解説

設問のSQL文は、Oracle独自の結合構文です。

Oracle独自の結合構文では、
・結合する表名は,(カンマ)で区切ってFROM句に指定
・結合条件はWHERE句に指定
・結合条件以外の条件はWHERE句に指定した結合条件の後にAND演算子で指定
します。

設問のSQL文ではEMPLOYEES表と、部署ごとの最低給与を問合せる( )で囲まれた副問合せをFROM句に指定し、両者を結合しています。
しかし、WHERE句には「e.salary > s.minsal」という検索条件しか指定されておらず、結合条件が欠けています。この場合エラーとはなりませんが、結合した全てのデータの組み合わせが返ってくるので正しい結果は得られません。

以上より、
・実行されるが正しい結果が返されない
が正解となります。

設問のSQL文の実行結果は次のようになります。


SQLを表示
SELECT e.employee_name, e.salary, e.department_id, s.minsal
FROM employees e, (SELECT department_id, MIN(salary) minsal FROM employees GROUP BY department_id) s
WHERE e.salary > s.minsal
ORDER BY e.department_id, e.salary;


正しく実行するには、WHERE句に結合条件を指定します。


SQLを表示
SELECT e.employee_name, e.salary, e.department_id, s.minsal
FROM employees e, (SELECT department_id, MIN(salary) minsal FROM employees GROUP BY department_id) s
WHERE e.department_id = s.department_id
AND e.salary > s.minsal
ORDER BY e.department_id, e.salary;

参考

Oracle Databaseには、Oracle独自の結合構文があります。
構文は以下の通りです。

 SELECT [表接頭辞.]列名 [, [表接頭辞.]列名 ...]
 FROM 表名1, 表名2
 WHERE 結合条件
 [AND 結合条件以外の条件];

 
 

SQLを表示
SELECT d.department_id, d.department_name, e.employee_id,e.employee_name
FROM departments d, employees e
WHERE d.department_id = e.department_id
 AND salary BETWEEN 200000 AND 450000;


Oracle独自の結合構文では、
・結合する表名は,(カンマ)で区切ってFROM句に指定
・結合条件はWHERE句に指定
・結合条件以外の条件はWHERE句に指定した結合条件の後にAND演算子で指定
します。

ON句を使用した結合同様に、結合する2つの表にある同じ名前の列をSELECT句やWHERE句に指定する場合は、必ず表接頭辞を使用して列を指定しなければなりません。


 
SQLを表示
SELECT department_id, d.department_name, e.employee_id,e.employee_name
FROM departments d, employees e
WHERE d.department_id = e.department_id
 AND salary BETWEEN 200000 AND 450000;


なお、ON句で結合条件を指定した場合とOracle独自の結合構文とではパフォーマンスに違いはありません。

上に戻る

クロス結合のGROUP BY につて

公開日 2022/05/01

SELECT e.employee_name, e.salary, e.department_id, s.minsal
 FROM employees e, (SELECT department_id, MIN(salary) minsal FROM employees GROUP BY department_id) s
 WHERE e.salary > s.minsal
 ORDER BY e.department_id, e.salary;

クロス結合することは分かりました。しかし、部署ごとにGROUP BYしているので、部署ごとに対して一番少ないsalary(一つの値のみ)が表示されるはずなのに、表示例を見ると2つ表示されています。

department_idが1に対してminsalが200000と300000

なぜこのように表示されるのでしょうか。

2022/05/02 13:13

解説の1つ目の表示例ですよね。

しかし、WHERE句には「e.salary > s.minsal」という検索条件しか指定されておらず、結合条件が欠けています。この場合エラーとはなりませんが、結合した全てのデータの組み合わせが返ってくるので正しい結果は得られません。

と解説に書いてあるように、設問のSQL文に結合条件が指定されていないのでこのような結果になるようですよ。
正しいSQL文と結果は2つ目の図の方です。


コメント

h hayasidaisi

2022/05/03 09:21

質問に答えていただいてありがとうございます。 ということは、副問い合わせの中のGROUP BY department_idがなくても表示結果は同じということでよろしいでしょうか? だとすると、このようなクロス結合された場合GROUP BYのような条件は無効になると考えていいですか?

h hayasidaisi

2022/05/03 09:29

わかりました。(多分) GROUP BY したすべてのMIN(salary)とクロス結合するから複数のMIN(salary)が表示されるんですね。

q quensan

2022/05/06 18:22

そうですね。employees表と副問い合わせの全てのデータの組み合わせになるので。

この返信に対して
コメントを記入できます

この投稿に対して返信しませんか?