NATURAL JOINとUSING
異なるレコード(行)を1つのレコードとして出力する方法を結合(JOIN)といいます。また、異なるレコードどうしが結合できる/できないの条件を結合条件、互いのレコードの値が一致することを条件とする場合を等価結合といいます。
結合の基本構文は次のとおりです。
SELECT (表名n.)列名, …… FROM 表名1 JOIN 表名2 ON 表名1.結合列名 = 表名2.結合列名
結合条件はON
句で記述します。ただし、等価結合では結合条件に指定する列名は、結合する表どうしで同じである場合が多いので、いちいちON
句に結合条件を記述しなくても、列名で察してくれないかなと思うことがあります。それを実現してくれるのが、自然結合(NATURAL JOIN)です。
また、結合列以外にも同じ名前の列が存在するという場合にはJOIN USING
を使用し、「結合条件に使用する列は(同じ名前の列が複数ある中で)この列だよ」と指定できるのでした。
それを踏まえて、次の問題を考えてみましょう。
問1
次の3つの表を確認してください。
SQL> desc customers 名前 NULL? 型 ----------------------------- -------- -------------------- CUST_ID NOT NULL NUMBER CUST_FIRST_NAME NOT NULL VARCHAR2(20) CUST_LAST_NAME NOT NULL VARCHAR2(40) CUST_GENDER NOT NULL CHAR(1) CUST_YEAR_OF_BIRTH NOT NULL NUMBER(4) CUST_MAIN_PHONE_NUMBER NOT NULL VARCHAR2(25) CUST_EMAIL VARCHAR2(50) SQL> desc products 名前 NULL? 型 ----------------------------- -------- -------------------- PROD_ID NOT NULL NUMBER(6) PROD_NAME NOT NULL VARCHAR2(50) PROD_DESC NOT NULL VARCHAR2(4000) PROD_LIST_PRICE NOT NULL NUMBER(8,2) PROD_MIN_PRICE NOT NULL NUMBER(8,2) SQL> desc sales 名前 NULL? 型 ----------------------------- -------- -------------------- PROD_ID NOT NULL NUMBER CUST_ID NOT NULL NUMBER TIME_ID NOT NULL DATE CHANNEL_ID NOT NULL NUMBER PROMO_ID NOT NULL NUMBER QUANTITY_SOLD NOT NULL NUMBER(10,2) AMOUNT_SOLD NOT NULL NUMBER(10,2)
次の問い合わせを実行しました。
SELECT DISTINCT p.prod_id,prod_name,cust_id,cust_last_name FROM products p NATURAL JOIN sales s JOIN customers c USING (cust_id);
この問い合わせに対して、正しい記述を選びなさい。
- a. 正常に実行される
- b. 1つのSQLに、NATURAL JOINとJOIN USINGの両方を使うことはできないので、エラーが発生する
- c. NATURAL JOINで使用する結合列に表名を指定することはできなので、エラーが発生する
- d. JOIN USINGで使用する結合列は表名を指定しなければいけないので、エラーが発生する
- e. NATURAL JOINは3つ以上の表の結合には使用できないので、エラーが発生する
- f. JOIN USINGは3つ以上の表の結合には使用できないので、エラーが発生する
まずは、設問のSQLを実行してみましょう。
SQL> SELECT DISTINCT p.prod_id,prod_name,cust_id,cust_last_name 2 FROM products p 3 NATURAL JOIN sales s 4 JOIN customers c 5 USING (cust_id); SELECT DISTINCT p.prod_id,prod_name,cust_id,cust_last_name * 行1でエラーが発生しました。: ORA-25155: NATURAL結合で使用される列は修飾子を持てません。
実行結果から分かるように、選択肢aは不正解で、正解は選択肢cです。 NATURAL JOIN
およびJOIN USING
は、ON
句を使用して結合条件を記述しない代わりに、同じ名前の列を結合列として使用します。 このとき、結合列を表名で修飾してはいけません。
設問のSQLから、products表とsales表の結合列であるprod_idの表名修飾をなくしただけのSQLを実行してみましょう。
SQL> SELECT DISTINCT prod_id,prod_name,cust_id,cust_last_name 2 FROM products p 3 NATURAL JOIN sales s 4 JOIN customers c 5 USING (cust_id); PROD_ID PROD_NAME CUST_ID CUST_LAST_NAME ---------- --------------------------------- ---------- ------------ 13 5MP Telephoto Digital Camera 2310 Hale 13 5MP Telephoto Digital Camera 5681 Wagner (途中省略) 147 Extension Cable 7390 Ziluca 147 Extension Cable 2115 Overton 279954行が選択されました。
正常に実行されることから、次のことが分かります。
-
1つのSQLに、
NATURAL JOIN
とJOIN USINGの
両方を使うことができる(選択肢bは不正解) -
JOIN USING
で使用する結合列は、表名を指定する必要がない(選択肢dは不正解) -
NATURAL JOIN
は、3つ以上の表の結合には使用できる(選択肢eは不正解) -
JOIN USING
は、3つ以上の表の結合には使用できる(選択肢fは不正解) -
NATURAL JOIN
やJOIN USING
句を使用した結合のSELECT
句に、DISTINCT
を使用することができる
3つ以上の表の結合を行う場合、NATURAL JOIN
とJOIN USING
だけでなく、後述するON
句を使用した外部結合でも自己結合でも、何でも混在できることも合わせて覚えておいてください。
また、どんなときでも、NATURAL JOIN
とJOIN USING
の結合列は表名で修飾してはいけませんが、結合列以外は表名で修飾できること、それどころか、ON
句を使用した結合の場合は結合列(列名が同じ)の表名修飾が必要であることも忘れないでください。