自然結合と内部結合の違い


197

自然結合と内部結合の違いは何ですか?


3
これは、他では扱われていないINNER結合とNATURAL結合についての質問なので、この質問は他の質問と重複していません。

1
かつて、これは「左、右、外部、内部結合の違い何ですか」の複製としてクローズされました、その質問は内部結合と自然結合の違いには対処していません。
Jonathan Leffler、2015年

回答:


250

INNER JOINとNATURAL JOINの重要な違いの1つは、返される列の数です。

考慮してください:

TableA                           TableB
+------------+----------+        +--------------------+    
|Column1     | Column2  |        |Column1  |  Column3 |
+-----------------------+        +--------------------+
| 1          |  2       |        | 1       |   3      |
+------------+----------+        +---------+----------+

INNER JOIN列1のテーブルAとテーブルBの戻ります

SELECT * FROM TableA AS a INNER JOIN TableB AS b USING (Column1);
SELECT * FROM TableA AS a INNER JOIN TableB AS b ON a.Column1 = b.Column1;
+------------+-----------+---------------------+    
| a.Column1  | a.Column2 | b.Column1| b.Column3|
+------------------------+---------------------+
| 1          |  2        | 1        |   3      |
+------------+-----------+----------+----------+

NATURAL JOIN列1のテーブルAとテーブルBのは返します。

SELECT * FROM TableA NATURAL JOIN TableB
+------------+----------+----------+    
|Column1     | Column2  | Column3  |
+-----------------------+----------+
| 1          |  2       |   3      |
+------------+----------+----------+

列の繰り返しは避けられます。

(標準文法のAFAICTでは、自然結合では結合列を指定できません。結合は厳密に名前ベースです。Wikipediaも参照してください。)

チートは出力を内部結合であります; a.およびb.部品は、列名にはならないでしょう。あなただけの必要があるだろうcolumn1column2column1column3見出しとして。


2
2つのテーブルTableA(Column1、Column2)とTableB(Column2、Column3)があります。

16
出力の列を折りたたむことは、自然結合の最も重要ではない側面です。知っておくべきことは、(A)同じ名前のフィールドに自動的に結合すること、および(B)それが最も予期しないときにs ***をf ***上げることです。私の世界では、自然結合を使用することが解雇の根拠です。

8
@JonofAllTrades正確NATURAL JOINに何が台無しになるのか、なぜそれが予想外であるのか、そしてあなたがどの世界にいるのかについて詳しく説明できますか?
ブライソン2014年

35
これは、user166390の回答で多少対処されています。との自然な結合があるCustomersEmployeesEmployeeIDます。 フィールドEmployeesもありManagerIDます。全部大丈夫です。その後、ある日、誰かがテーブルにManagerIDフィールドを追加しCustomersます。あなたの結合は壊れません(それは慈悲でしょう)、代わりにそれは2番目のフィールドを含み、正しく動作しません。したがって、一見害のない変更によって、関連性の低いものだけが破壊される可能性があります。ひどい。自然結合の唯一の利点は、タイピングを少し節約することであり、欠点はかなりあります。

2
@ジョナサン、あなたの答えについて、あなたはそれSELECT * FROM TableA INNER JOIN TableB USING (Column1)が4列を与えると述べました。SELECT * FROM TableA INNER JOIN TableB USING (Column1)SELECT * FROM TableA NATURAL JOIN TableBは等しいため、これは正しくありません。どちらも3列です。
パセリエ

81
  • 内側は、接合されたテーブルに一致する行が返される最初のテーブルからの行のために必要とされるものであるジョイン
  • アウタージョインは、結合テーブル内の一致する行がされているものであるしない返される最初のテーブルからの行のために必要
  • 自然の参加は、(あなたはどちらか持つことができます参加しているnatural leftnatural right)であることを参加の条件を前提としているところ、両方のテーブルの試合で同じ名前の列

ペストのような自然結合の使用は避けます。自然結合は次のとおりです。

  • ない標準SQL [SQL 92]とそれゆえないポータブル、特に読めません(ほとんどのSQLコーダによる)と、おそらくさまざまなツール/ライブラリでサポートされていません
  • 有益ではありません。スキーマを参照しないと、どの列が結合されているのかわからない
  • 結合条件は目に見えないほどスキーマの変更に対して脆弱です-複数の自然結合列があり、そのような列の1つがテーブルから削除された場合、クエリは引き続き実行されますが、おそらく正しく実行されず、この動作の変更は通知されません
  • 努力する価値はほとんどありません。タイピングの約10秒を節約するだけです

2
私はアウターの左/右が言及されるべきだと思います(アウターはまったく言及されているので)。しかし、それ以外の点では、素晴らしく簡潔です。見栄えのよいSQLレコード図の例が欠けているだけです。

2
自然左と自然右も存在します。しかし、はい、それでもそれらを避けてください。
MatBailie、2012年

1
@Bohemian、「ペストのようにそれらを回避する」に関して、それらが便利になる自然結合の実際の使用例があります。mariadb.com/kb/en/sql-99/natural-join "...カジュアルな外観の" Books NATURAL JOIN Checkouts"は、データベースの命名規則が正式で強制されている場合にのみ可能です。..."
Pacerier

2
@sqlvovelコメントに多くの誤りがあります。具体的には正しくありません。結合列「選択リストで指定」することはできません。自然結合の定義は、*すべての同じ名前の列*で結合することです。MySQL docから:2つのテーブルのNATURAL [LEFT] JOINは、両方のテーブルに存在するすべての列に名前を付けるUSING句を使用したINNER JOINまたはLEFT JOINと意味的に同等であると定義されています。。そしてもう1つ- idユビキタスであり、参加するのに役に立たないため、実際には役に立たない 通常の外部キー名はtablename_idです。自然結合は悪い、悪い、悪い考えです。
ボヘミアン

2
クエリに二重に返される列はありません。NJセマンティクスの利点の1つは、重複した列が返されないことです。前のクエリも、「エイリアスされていない結合条件があいまいなため」、「a」という列がt2に追加された場合に失敗するため、私のクエリよりも「安全性が低く」なりました。NJに対するあなたの偏見は、標準SQLが適切にサポートされている製品でそれを試していないという事実に基づいていると思います。ここでの質問は、MySQLではなくSQLに関するものです。それが非標準であるというあなたの答えをまだ修正していません。
nvogel

27

自然結合は入力を回避するための単なるショートカットであり、結合は単純で、同じ名前のフィールドに一致すると想定されています。

SELECT
  *
FROM
  table1
NATURAL JOIN
  table2
    -- implicitly uses `room_number` to join

と同じです...

SELECT
  *
FROM
  table1
INNER JOIN
  table2
    ON table1.room_number = table2.room_number

ただし、ショートカット形式ではできないのは、より複雑な結合です...

SELECT
  *
FROM
  table1
INNER JOIN
  table2
    ON (table1.room_number = table2.room_number)
    OR (table1.room_number IS NULL AND table2.room_number IS NULL)

2
@JonathanLeffler-MySQLでは確かに。
MatBailie、2012年

3
OK-面白い。SQL標準ではこれを許可していないようです(ただし、拡張は常に可能です)。
Jonathan Leffler、2012年

この非標準構文を許可するDBMSはどれNATURAL JOIN ... USING ()ですか。標準のいずれかであるa NATURAL JOIN ba JOIN b USING (c)
ypercubeᵀᴹ

1
「タイプするのを避けるためのただの近道」は誤った表現です。最も重要な機能は、列が重複しないことです。
onedaywhen

...たとえば、自然結合を使用するクエリの結果にはという名前の列が1つだけroom_numberあるのに対し、内部結合にはという名前の列が2つありますroom_number
onedaywhen

13

SQLは、多くの点でリレーショナルモデルに忠実ではありません。SQLクエリの結果はリレーションではありません。重複した名前の列、「匿名の」(名前のない)列、重複した行、nullなどがある可能性があります。SQLは、列の順序などに依存しているため、テーブルをリレーションとして扱いません。

NATURAL JOINSQLの背後にある考え方は、リレーショナルモデルにより忠実になることを容易にすることです。NATURAL JOIN2つのテーブルの結果には、名前によって重複が排除された列が含まれるため、匿名の列はありません。同様に、UNION CORRESPONDINGそしてEXCEPT CORRESPONDINGレガシーで列の順序でアドレスSQLの依存に提供されていますUNION構文。

ただし、すべてのプログラミング手法と同様に、有用であるためには規律が必要です。NATURAL JOIN結合が同じ名前の列に暗黙的に含まれるため、成功するための1つの要件は、一貫して名前が付けられた列です(SQLで列の名前を変更する構文が冗長であることは残念ですが、副作用として、ベーステーブルの列に名前を付けるときの規則が奨励されます。VIEW s :)

SQL NATURAL JOINは等結合**ですが、これは有用性を妨げるものではありません。NATURAL JOINSQLでサポートされる唯一の結合タイプである場合でも、関係的に完全であることを考慮してください。

実際に、プロジェクション()NATURAL JOINを使用INNER JOINして記述できることは事実ですが、製品()および制限()を使用して記述できることSELECTも事実です。さらに、共通の列名のないテーブル間では、と同じ結果が得られることに注意してください。したがって、リレーションである結果のみに関心がある場合(そして、なぜそうならないのか?!)、必要な結合タイプはこれだけです。確かに、言​​語設計の観点からは、やなどの省略形があることは事実ですが、ほとんどすべてのSQLクエリは、構文的には異なりますが、意味的には同等の10の方法で記述できることを考慮してください。これがSQLオプティマイザを非常に困難にしている理由です。開発する。INNER JOINCROSS JOINWHERENATURAL JOINCROSS JOINNATURAL JOININNER JOINCROSS JOIN

以下は、意味的に同等なクエリの例です(通常の部品とサプライヤーデータベースを使用)。

SELECT *
  FROM S NATURAL JOIN SP;

-- Must disambiguate and 'project away' duplicate SNO attribute
SELECT S.SNO, SNAME, STATUS, CITY, PNO, QTY
  FROM S INNER JOIN SP 
          USING (SNO);                        

-- Alternative projection
SELECT S.*, PNO, QTY
  FROM S INNER JOIN SP 
          ON S.SNO = SP.SNO;

-- Same columns, different order == equivalent?!
SELECT SP.*, S.SNAME, S.STATUS, S.CITY
  FROM S INNER JOIN SP 
      ON S.SNO = SP.SNO;

-- 'Old school'
SELECT S.*, PNO, QTY
  FROM S, SP 
 WHERE S.SNO = SP.SNO;

**リレーショナル自然結合は、等結合ではなく、1の射影です。– philipxy


リレーショナル自然結合は、等結合ではなく、1の射影です。SQL自然結合は、SQL等価結合(重複可能)です-内部結合を使用して定義されます。
philipxy

@philipxy:ありがとう、私は修正をしました。誤解や誤解については、これまたは私の答えのいずれかを編集してください。私はまだ:)あなたから学んでいる
onedaywhen

9

NATURAL参加のためにわずか構文される特定の INNER参加-又は「等結合」 -と、構文が開封されると、両方同じ関係代数演算を表します。これは、「異なる種類の」結合ではありません。OUTERLEFT/ RIGHT)やCROSS結合の。

を参照してください 等結合ウィキペディアのセクションを:

自然結合は、等結合のさらなる特殊化を提供します。結合述語は、結合されたテーブルで同じ列名を持つ両方のテーブルのすべての列を比較することによって暗黙的に発生します。結果の結合テーブルには、同じ名前の列のペアごとに1つの列のみが含まれます。

ほとんどの専門家は、NATURAL JOINは危険であり、そのため使用を強く推奨しないことに同意します。危険なのは、別の列と同じ名前の新しい列を誤って追加したことです...

つまり、すべてのNATURALように書くことも加わりINNER参加する(その逆は真ではありません)。そのためには、述語を作成するだけです明示的に -例:USINGまたはON -)。Jonathan Lefflerが指摘したように、必要な結果セットの列を選択して、必要に応じて「重複」を回避します。

ハッピーコーディング。


NATURALキーワードはLEFTand RIGHT結合にも適用できます。同じことが適用されます。NATURAL LEFT/RIGHT結合は、特定の LEFT/RIGHT結合の短い構文にすぎません。)


2
"NATURALジョインは[snipped]" equi-join "の短い構文です-構文がアンラップされると、両方が同じリレーショナル代数を表します"-正解です。これはリレーショナル代数にも当てはまりますが、答えは壊れますその後、例えば、「ほとんどの専門家は、NATURAL JOINは危険であり、したがって、その使用を強く阻止することに同意します」-関係代数のどの専門家がそれを言っているのですか?
2016年

2

自然結合:2つのテーブルのすべての列の組み合わせまたは組み合わせた結果です。2番目のテーブルに関して最初のテーブルのすべての行を返します。

内部結合:この結合は、列名のいずれかが2つのテーブルでsxameでなければならない場合に機能します。


3
私はあなたの答えが十分に明確ではないと思います、そしてそれを修正するために大規模な書き直しをするでしょう。
9:31

0

自然結合では、2つのテーブルがすべての一般的な列に基づいて結合されます。

共通の列:両方のテーブルで同じ名前の列で、両方のテーブルで互換性のあるデータ型があります。=演算子のみを使用できます

内部結合では、ON句で言及されている共通の列に基づいて2つのテーブルが結合されます。

共通の列:両方のテーブルに互換性のあるデータ型がある列ですが、同じ名前である必要はありません。あなたが好きなだけで任意の比較です演算子を使用することができ=<=>=<><>


-2

違いは、natuall結合の共通列winの内部(equi / default)joinと自然結合のintは1回で表示されますが、inner / equi / default / simple結合の共通列は2回表示されます。


-2

内部結合と自然結合はほとんど同じですが、両者にはわずかな違いがあります。違いは、条件を指定する必要がない自然結合ですが、内部結合条件では必須です。内部結合で条件を指定すると、結果のテーブルはデカルト積のようになります。


結合条件を指定する必要がないのはなぜですか?どのような状況で内部結合に条件を指定すると、デカルト積のような結果になりますか?
onedaywhen

外部結合と内部結合を「ほぼ同じ」と呼ぶのは少し控えめな言い方です。おそらく、評価について詳しく説明できますか?
TMOTTM

-3
mysql> SELECT  * FROM tb1 ;
+----+------+
| id | num  |
+----+------+
|  6 |   60 |
|  7 |   70 |
|  8 |   80 |
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
+----+------+
6 rows in set (0.00 sec)

mysql> SELECT  * FROM tb2 ;
+----+------+
| id | num  |
+----+------+
|  4 |   40 |
|  5 |   50 |
|  9 |   90 |
|  1 |    1 |
|  2 |    2 |
|  3 |    3 |
+----+------+
6 rows in set (0.00 sec)

INNER JOIN:

mysql> SELECT  * FROM tb1 JOIN tb2 ; 
+----+------+----+------+
| id | num  | id | num  |
+----+------+----+------+
|  6 |   60 |  4 |   40 |
|  7 |   70 |  4 |   40 |
|  8 |   80 |  4 |   40 |
|  1 |    1 |  4 |   40 |
|  2 |    2 |  4 |   40 |
|  3 |    3 |  4 |   40 |
|  6 |   60 |  5 |   50 |
|  7 |   70 |  5 |   50 |
|  8 |   80 |  5 |   50 |
.......more......
return 36 rows in set (0.01 sec) 
AND NATURAL JOIN :

    mysql> SELECT  * FROM tb1 NATURAL JOIN tb2 ;
    +----+------+
    | id | num  |
    +----+------+
    |  1 |    1 |
    |  2 |    2 |
    |  3 |    3 |
    +----+------+
    3 rows in set (0.01 sec)

-4

内部結合、列名が同じである2つのテーブルを結合します。

自然結合、列名とデータ型が同じである2つのテーブルを結合します。


これは完全に間違っています。A NATURAL JOIN(数年前に指摘されたように)は、列名が同じであるものです。データ型は同じである必要はありません。INNER JOINニーズに使用されるフィールドは、同じ名前である必要はありません。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.