問題ID:20000

  • フォーラムは新サイトへ移行しました。
  • このフォーラムではゲスト投稿が禁止されています
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 .2 .3 | 投稿日時 2018-10-11 19:02
takuto0622  新米   投稿数: 3
以下の問題、1番が正解なのは理解できるのですが、なぜ4番も正解なのか分かりません。
どなたかご教示お願いします。

-----------------------------------------------

EMPLOYEES表から、上司のいる従業員の名前を表示します。
どの問合せを使用しますか(2つ選択して下さい)。

1.
○ SELECT e.employee_name FROM employees e
WHERE EXISTS (SELECT * FROM employees m WHERE e.manager_id = m.employee_id);

2.
SELECT m.employee_name FROM employees m
WHERE EXISTS (SELECT * FROM employees e WHERE e.manager_id = m.employee_id);

3.
SELECT e.employee_name FROM employees e
WHERE EXISTS SELECT * FROM employees m WHERE e.manager_id = m.employee_id;

4.
○ SELECT employee_name FROM employees
WHERE manager_id IN (SELECT employee_id FROM employees);

解説:
EXISTS演算子は、副問合せの結果が1行以上返される場合にTRUEとして評価される演算子です。
主問合せのWHERE句に列名と比較演算子を指定する代りに、EXISTS演算子を指定します。

 WHERE EXISTS (副問合せ)

EXISTS演算子で設問の結果を得るには、主問合せで取り出したEMPLOYEES表 e の各行に対して副問合せを実行し、EMPLOYEES表 m のEMPLOYEE_ID列にMANAGER_ID列と同じ値があればTRUEを返し、上司がいる従業員として主問合せの行を表示します。
このSQL文はIN演算子を使用したSQL文にも置き換えられます。

以上より、
・SELECT e.employee_name FROM employees e
 WHERE EXISTS (SELECT * FROM employees m WHERE e.manager_id = m.employee_id);
・SELECT employee_name FROM employees
 WHERE manager_id IN (SELECT employee_id FROM employees);
が正解となります。
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2018-10-11 22:19
arashi1977  長老 居住地: 広島  投稿数: 1715
引用:
以下の問題、1番が正解なのは理解できるのですが、なぜ4番も正解なのか分かりません。
どなたかご教示お願いします。
これはテーブルの構成がわかってないとイメージしにくそうですね。問題集のトップページにテーブル作成するSQLがあるのでそこも合わせて確認してください。

イメージするために別のところから先に行きますが
・jobsテーブルの中身を見ると、job_idが1001,1002というのは役職が上(取締役、管理職)の人であることがわかります。
・employeesテーブルの中身を見ると、job_idが1001,1002ではない人はmanager_idがNULLではない事がわかります。ここから、manager_idは「上司」を意味すると読み取れます。
・job_idとemployee_idの最小値が同じ1001から始まるので混乱しそうですが、manager_idはdepartmentsテーブルとemployeesテーブルの両方にあるので、ここはemployee_idが入るのではないかと考えられます(employeesテーブルのレコードからすると、job_idが1002(管理職)の人のemployee_idが入っていることから推測)

各テーブルの関係が見えたので、ご質問の内容に移ります。疑問を持たれたSQLは
SELECT employee_name FROM employees
WHERE manager_id IN (SELECT employee_id FROM employees);
ですが、順に考えると
・サブクエリでemployeesテーブルからemployee_idのリスト(全従業員のid)を取得
・employeesテーブルのmanager_idに、取得したemployee_idのどれか(INで指定していますので、すべての従業員IDのどれでもマッチする)が含まれている行(=設問の「上司のいる従業員」)を取得
・取得した行のemployee列を表示
となりますので、設問の要件を満たすといえます。

こんな感じでどうでしょうか?
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2018-10-12 13:00
takuto0622  新米   投稿数: 3
ご回答ありがとうございます!

ご回答を読ませていただくと「なるほど〜」と思うのですが、
jobsテーブルがあることは問題のどこから読み取ればよいのでしょうか?
(もしかして、そもそもjobsテーブルやdepartmentsテーブルなどが存在する前提で全ての問題が作られているということですか?)
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2018-10-12 13:06 | 最終変更
arashi1977  長老 居住地: 広島  投稿数: 1715
引用:
jobsテーブルがあることは問題のどこから読み取ればよいのでしょうか?
(もしかして、そもそもjobsテーブルやdepartmentsテーブルなどが存在する前提で全ての問題が作られているということですか?)
そのはずですね。問題集のトップに以下のように書かれていますので、全体的につじつまは合うようになっていると思います。
引用:
本問題集のSQL文を実行する為のテーブル等は、以下の3つのSQLファイルを順に実行する事で作成できます。但し、個人的に構築した検証環境で実行して下さい。本番環境や、それに準じる環境で実行した場合、既存のデータを壊す可能性があります。
1. 管理者で>createUser.sqlを実行。→pingtとuserAの2ユーザー(パスワード:oracle)を作成 2. pingtユーザで>setup.sqlを実行。 3. userAユーザで>setupByUserA.sqlを実行。

あとは解説にもありますけど
引用:
このSQL文はIN演算子を使用したSQL文にも置き換えられます。
ですね。そもそもEXISTSについての問題のようですので、1が正解だとわかるのであれば変換して4も正解、というのは何となく分かるかなーと
前の投稿 - 次の投稿 | 親投稿 - 子投稿.1 | 投稿日時 2018-10-12 21:16
takuto0622  新米   投稿数: 3
前提となるテーブル群があったんですね!納得しました。
テーブルを作成するためにも、検証環境の構築?とは何か調べてみます。
(超初心者なものでスミマセン…)

ご回答ありがとうございました。
前の投稿 - 次の投稿 | 親投稿 - 子投稿なし | 投稿日時 2018-10-13 11:05
arashi1977  長老 居住地: 広島  投稿数: 1715
引用:
前提となるテーブル群があったんですね!納得しました。
テーブルを作成するためにも、検証環境の構築?とは何か調べてみます。
(超初心者なものでスミマセン…)
OracleXEってので調べるといいかもしれませんよ
SQLだけとりあえず実行できればいいってのだと、SQLite3について調べると良いです。提供されているSQLを少し修正する必要はありますが、手軽に実行できて良いですよー

  >フォーラム検索へ


Copyright (c) 2020 Ping-t All rights reserved.