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句を使用した結合の場合は結合列(列名が同じ)の表名修飾が必要であることも忘れないでください。

 
              
               
              
               
              
               
              
               
              
               
                  
                   
                  
                 
                  
                 
                  
                 
                                            
                                         
                                            
                                         
                                            
                                         
                                            
                                         
                                            
                                         
                                            
                                         
 
                    