2017-01-11 6 views
3

私はOracle SQLを学んでいますが、今はジョインズの章で悩んでいます。私はなぜ知らないSA_REP 80JoinとNatural Joinの違いは何ですか?

SELECT   employee_id, job_id, department_id, 
       e.last_name, e.hire_date, j.end_date 
FROM   employees e 
NATURAL JOIN job_history j; 

176に参加テイラー24/03/2006 31/12/2006

SELECT   e.employee_id, e.job_id, e.department_id, 
       e.last_name, e.hire_date, j.end_date 
FROM   employees e 
JOIN   job_history j 
ON    (e.department_id = j.department_id) 
ORDER BY  employee_id, last_name; 

172 SA_REP 80 Bates 24/03/2007 31/12/2006 
173 SA_REP 80 Kumar 21/04/2008 31/12/2007 
173 SA_REP 80 Kumar 21/04/2008 31/12/2006 
174 SA_REP 80 Abel 11/05/2004 31/12/2007 
174 SA_REP 80 Abel 11/05/2004 31/12/2006 
175 SA_REP 80 Hutton 19/03/2005 31/12/2007 
175 SA_REP 80 Hutton 19/03/2005 31/12/2006 
176 SA_REP 80 Taylor 24/03/2006 31/12/2007 
176 SA_REP 80 Taylor 24/03/2006 31/12/2006 
177 SA_REP 80 Livingston 23/04/2006 31/12/2007 
177 SA_REP 80 Livingston 23/04/2006 31/12/2006 

に参加し、自然との違いを理解することはできません結合と自然結合の両方に似た機能がある場合、私は異なる結果を受け取ります。

+2

IMO、「Nature Join」は、2つのテーブルの同じ名前を持つすべての列をチェックして結合する**暗黙の**結合列を使用します。 'Join'では、** ON文のjoin列を明示的に宣言する必要があります(同じ名前かもしれないし、おそらく2つのテーブルには同じ10のカラム名がありますが、2つの異なるカラム名を結合するだけです)。 –

+2

自然な結合を決して使用しない理由の良い例です。あなたのケースでは、自然結合はより多くの列を使用して結合し、より制限します。それらの列はどれですか?私はそれが表示されていないとして知らない! –

+0

プレフィックスがそのテーブル名によって単に暗示される短い属性が、他のテーブルを含む関係演算子で使用されるときに問題を引き起こす良い例です。 'employ_end_date'が明白になる' employees'の 'end_date'です。 – onedaywhen

答えて

10

natural joinを使用しないでください。それは起こるのを待っているバグです。

明示的なjoinには、テーブル間の一致条件を一覧表示するon句があります。あなたの例では、この目的のためにdepartment_idが使用されています(他の列も利用可能です)。

using句は、別の非常に便利な代替手段です。これは、両方のテーブルのdepartment_idを見つけて、結合条件のためにそれを使用しています

FROM employees e JOIN 
    job_history j 
    USING (department_id) 

:としてあなたはそれを使用しています。

NATURAL JOINは、同じ表のすべての列を追加します。あなたの場合、これはdepartment_idと他の列になります。

問題は、あなたが経験しているように、joinにどのような列が使用されているのかわかりません。さらに悪いことに、明示的なの外部キー参照は使用されません。

クエリで何が起きているのかが特定されていないため、間違いやバグの対象範囲がたくさんあります。 NATURAL JOINの実際の必要性はないので、ONUSINGを使用することを学ぶだけでよいでしょう。

+1

'NATURAL JOIN'を使用する唯一の状況(と私はそれが役に立つと思います)は、ネストされたテーブルの場合です。 'SELECT * FROM MY_TABLE NATURAL JOIN TABLE(NESTED_TABLE_COLUMN) ' –

+0

あなたの助けをありがとう!!! – Rattlesnake

2

明示的に明示する必要があります。最初のクエリは、2番目のクエリと意味的に同じではないため、別の結果が得られます。 - ショック

WITH e AS 
    (SELECT employee_id, job_id, department_id, 
       last_name, hire_date 
     FROM employees), 
    j AS 
    (SELECT department_id, end_date 
     FROM job_history) 
SELECT * 
    FROM e NATURAL JOIN j 
ORDER 
    BY employee_id, last_name; 

、上記のクエリでは、私が持っているにもかかわらずにNO「起こるのを待っているバグが」ありません。ここで

NATURAL JOINバージョンの提案REWITEです!ホラー! - NATURAL JOINに加えてSELECT *を使用します(両方ともSQL flockに禁忌)。列がテーブルemployeesおよびjob_historyに追加されるシナリオからクエリを保護します。

+0

ご協力ありがとうございます。私はOracleプログラミングでは新しいので、この記事を作成しましたが、最近はSQL結合についてもう少し詳しく読んでいます。今私はPLSQLを練習しており、Oracle SQLについて詳しく知っています。再度、感謝します!!! – Rattlesnake

関連する問題