助け合いフォーラム

Oracle DB

Oracle Master Silver SQL 2019(1Z0-071)
問題ID : 26874
問題を開く
PROMOTIONS表とSALES3表の構造を確認して下さい。





プロモーション期間中に売れた製品の情報を表示します。
以下のSQL文の実行結果について正しいものはどれですか。

 SELECT p.promo_name, p.promo_begin_date, p.promo_end_date, s.time_id, s.quantity_sold
 FROM promotions p JOIN sales3 s
 ON s.time_id BETWEEN p.promo_begin_date AND NVL(p.promo_end_date, SYSDATE);

正解

結合条件が誤っているので違う結果が返される

解説

設問のSQL文では、ON句にBETWEEN演算子を使用して非等価結合の条件を指定していますが、これですとTIME_ID列(売れた日)が全プロモーションの期間内に合致する行が全て取り出されてしまい、設問の条件に該当しません。
各プロモーションの期間中に売れた製品の情報のみを取り出すには、PROMOTIONS表とSALES3表のPROMO_ID列を結合列として結合条件に指定し、ANDでBETWEEN演算子を続けて取り出す行の条件を指定する必要があります。

 SELECT p.promo_name, p.promo_begin_date, p.promo_end_date, s.time_id, s.quantity_sold
 FROM promotions p JOIN sales3 s
 ON p.promo_id = s.promo_id
 AND s.time_id BETWEEN p.promo_begin_date AND NVL(p.promo_end_date, SYSDATE);

NVL関数は、PROMO_END_DATE列が入力されていない現在進行中のプロモーションも正しく条件に合致するように使用しています。

以上より、
・結合条件が誤っているので違う結果が返される
が正解となります。

設問のSQL文の実行結果は次のようになりますが、希望の結果ではありません。



ON句に正しい結合条件を指定して修正したSQL文の実行結果は次のようになります。


SQLを表示
SELECT p.promo_name, p.promo_begin_date, p.promo_end_date, s.time_id, s.quantity_sold
FROM promotions p JOIN sales3 s
ON p.promo_id = s.promo_id
AND s.time_id BETWEEN p.promo_begin_date AND NVL(p.promo_end_date, SYSDATE);

参考

ON句を使用した結合では、結合条件をON句に指定します。
自然結合やUSING句での結合とは異なり、列名が違っていても結合列として指定できます。
構文は以下の通りです。

 SELECT [表接頭辞.]列名 [, [表接頭辞.]列名 ...]
 FROM 表名1 JOIN 表名2 ON [表名1の表接頭辞.]列名 = [表名2の表接頭辞.]列名
 [WHERE ...];

 
 
SQLを表示
SELECT department_name, employee_name
FROM departments JOIN employees
 ON departments.department_id = employees.department_id;


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


 
SQLを表示
SELECT department_id, department_name, employee_name
FROM departments JOIN employees
 ON departments.department_id = employees.department_id;


また、ON句は、「列名 = 列名」のような等価結合の結合条件を指定する場合のほか、「<,>,<=,>=,BETWEEN」などの演算子を使用して非等価結合の結合条件を指定する場合にも使用します。


 
SQLを表示
SELECT employee_name, salary, grade
FROM employees JOIN grade
 ON employees.salary BETWEEN grade.low AND grade.high;


[取り出す行を指定した表の結合]
表の結合時、結合した表から取り出したい行を指定してSQL文を実行できます。
行を指定する場合は、取り出す行の条件をWHERE句に指定します。

 SELECT 表別名.列名 [,表別名.列名 ...]
 FROM 表名1 表別名1 JOIN 表名1 表別名2
  ON 表別名1.列名 = 表別名2.列名
 WHERE 取り出す行の条件
  AND 取り出す行の条件
  AND ...;

 
 
SQLを表示
SELECT e.employee_id, d.department_name, e.employee_name
FROM departments d JOIN employees e
 ON d.department_id = e.department_id
WHERE e.hiredate >= '2005-10-01';


取り出す行の条件が複数ある場合は、WHERE句に1つ目の条件を記述し、その後に論理演算子ANDを使用して2つ目以降の条件を記述します。
WHERE句はON句による結合の他、NATIRAL JOIN、USING句による結合の場合も使用できます。


 
SQLを表示
SELECT e.employee_id, d.department_name, e.employee_name
FROM departments d JOIN employees e
 USING (department_id)
WHERE e.hiredate >= '2005-10-01';



 
SQLを表示
SELECT e.employee_id, d.department_name, e.employee_name
FROM departments d NATURAL JOIN employees e
WHERE e.hiredate >= '2005-10-01';


なお、ON句による結合の場合のみ、WHERE句は記述せず、ON句に記述した結合条件に論理演算子ANDで続けて取り出す行の条件を指定することもできます。

 SELECT 表別名.列名 [,表別名.列名 ...]
 FROM 表名1 表別名1 JOIN 表名1 表別名2
  ON 表別名1.列名 = 表別名2.列名
  AND 取り出す行の条件
  AND ...;

 
 
SQLを表示
SELECT e.employee_id, d.department_name, e.employee_name
FROM departments d JOIN employees e
 ON d.department_id = e.department_id
AND e.hiredate >= '2005-10-01';
上に戻る

結合条件について

退 退会ユーザ
公開日 2024/08/09

s.time_id BETWEEN p.promo_begin_date AND NVL(p.promo_end_date, SYSDATE);

上記の条件は解答だとON句に指定されていますが、
これはWHERE句に記載しても同じ意味でしょうか。

2024/08/15 15:21

ON句の代わりにWHERE句に記載することは可能ですが、その場合、FROM句でJOIN句が使用できなくなるため、結合するテーブルをカンマ区切りで列挙する必要があります。
ただ、複雑なSQL文の中で出力結果に対して複数のフィルタリング条件を適用する場合など、WHERE句内にANDやORを連ねることになるので、可読性は低くなるかもしれません。

SQL> SELECT p.promo_name, p.promo_begin_date, p.promo_end_date, s.time_id, s.quantity_sold
  2  FROM promotions p JOIN sales3 s
  3  ON p.promo_id = s.promo_id
  4  AND s.time_id BETWEEN p.promo_begin_date AND NVL(p.promo_end_date, SYSDATE);

PROMO_NAME		       PROMO_BE PROMO_EN TIME_ID  QUANTITY_SOLD
------------------------------ -------- -------- -------- -------------
プロモーション1                10-05-10 10-05-10 10-05-10            25
プロモーション5                10-10-01 10-12-31 10-11-05            21
プロモーション2                11-08-01 12-01-01 11-10-30            34
プロモーション2                11-08-01 12-01-01 11-12-31            15
プロモーション3                12-02-22          12-04-01             9
プロモーション4                11-12-24 12-12-31 12-07-10            16

6行が選択されました。

SQL> SELECT p.promo_name, p.promo_begin_date, p.promo_end_date, s.time_id, s.quantity_sold
  2  FROM promotions p JOIN sales3 s
  3  WHERE p.promo_id = s.promo_id
  4  AND s.time_id BETWEEN p.promo_begin_date AND NVL(p.promo_end_date, SYSDATE);
WHERE p.promo_id = s.promo_id
*
行3でエラーが発生しました。:
ORA-00905: キーワードがありません。


SQL> SELECT p.promo_name, p.promo_begin_date, p.promo_end_date, s.time_id, s.quantity_sold
  2  FROM promotions p, sales3 s
  3  WHERE p.promo_id = s.promo_id
  4  AND s.time_id BETWEEN p.promo_begin_date AND NVL(p.promo_end_date, SYSDATE);

PROMO_NAME		       PROMO_BE PROMO_EN TIME_ID  QUANTITY_SOLD
------------------------------ -------- -------- -------- -------------
プロモーション1                10-05-10 10-05-10 10-05-10            25
プロモーション5                10-10-01 10-12-31 10-11-05            21
プロモーション2                11-08-01 12-01-01 11-10-30            34
プロモーション2                11-08-01 12-01-01 11-12-31            15
プロモーション3                12-02-22          12-04-01             9
プロモーション4                11-12-24 12-12-31 12-07-10            16

6行が選択されました。

SQL>


コメント

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

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