内部結合では、2つの結合テーブルの各行に一致する列値が必要であり、アプリケーションで一般的に使用される結合操作ですが、最良の選択であるとは限りません。すべての状況で。内部結合は、結合述語に基づいて2つのテーブル(AとB)の列値を組み合わせることにより、新しい結果テーブルを作成します。クエリは、Aの各行をBの各行と比較して、結合述語を満たす行のすべてのペアを見つけます。 NULL以外の値を照合することで結合述語が満たされると、AとBの一致した行の各ペアの列値が結合されて結果行になります。
結合の結果は次のように定義できます。最初にテーブル内のすべての行のカルテシアン積(またはクロス結合)を取得し(テーブルAのすべての行をテーブルBのすべての行と結合)、次に結合述語を満たすすべての行を返す結果。実際のSQL実装では、通常、ハッシュ結合やソート/マージ結合などの他のアプローチが使用されます。これは、直積の計算が遅く、格納するために非常に大量のメモリが必要になることが多いためです。
SQLは、2つの異なる構文を指定します。結合を表現する方法:「明示的結合表記」と「暗黙的結合表記」。 「暗黙的な結合表記」は、データベースシステムで引き続きサポートされていますが、ベストプラクティスとは見なされなくなりました。
「明示的な結合表記」では、JOIN
キーワードを使用します。オプションで、前にINNER
キーワードを付けて結合するテーブルを指定し、ON
キーワードを使用して結合の述語を指定します。次の例:
SELECT employee.LastName, employee.DepartmentID, department.DepartmentName FROM employee INNER JOIN department ONemployee.DepartmentID = department.DepartmentID;
Employee.LastName | Employee.DepartmentID | Department.DepartmentName |
---|---|---|
Robinson | 34 | 事務 |
ジョーンズ | 33 | エンジニアリング |
スミス | 34 | クレリカル |
ハイゼンベルグ | 33 | エンジニアリング |
ラファティ | 31 | セールス |
「暗黙の結合表記」は単にtをリストします結合するためのテーブルは、SELECT
ステートメントのFROM
句で、コンマを使用して区切ります。したがって、クロス結合を指定し、WHERE
句は追加のフィルター述語を適用する場合があります(明示的な表記の結合述語と同等に機能します)。
次の例は前の例と同等ですが、今回は暗黙的な結合表記を使用しています。
SELECT employee.LastName, employee.DepartmentID, department.DepartmentName FROM employee, departmentWHERE employee.DepartmentID = department.DepartmentID;
例に示されているクエリ上記は、両方のテーブルのDepartmentID列を使用してEmployeeテーブルとDepartmentテーブルを結合します。これらのテーブルのDepartmentIDが一致する場合(つまり、結合述語が満たされる場合)、クエリは2つのテーブルのLastName、DepartmentID、およびDepartmentName列を結果行に結合します。 DepartmentIDが一致しない場合、結果行は生成されません。
したがって、上記のクエリの実行結果は次のようになります。
Employee.LastName | Employee.DepartmentID | Department.DepartmentName |
---|---|---|
ロビンソン | 34 | クレリカル |
ジョーンズ | 33 | エンジニアリング |
スミス | 34 | クレリカル |
ハイゼンベルグ | 33 | エンジニアリング |
ラファティ | 31 | 販売 |
従業員「Williams」と部門「Marketing」はクエリの実行結果に表示されません。これらのいずれにも、他のそれぞれのテーブルに一致する行はありません。「Williams」には関連する部門がなく、従業員には部門ID 35(「マーケティング」)がありません。目的の結果によっては、この動作は微妙なバグである可能性があります。これは、内部結合を外部結合に置き換えることで回避できます。
内部結合とNULL値編集
プログラマーはNULL値を含む可能性のある列でテーブルを結合する場合は、特に注意してください。結合条件で、結合列が残りの述語条件を適用する前。内部結合は、参照整合性を強制するデータベース、または結合列がNULLにならないことが保証されているデータベースでのみ安全に使用できます。多くのトランザクション処理リレーショナルデータベースは、原子性、整合性、分離、耐久性(ACID)データ更新標準に依存してデータの整合性を確保し、内部結合を適切な選択にします。ただし、トランザクションデータベースには通常、NULLにすることが許可されている望ましい結合列もあります。多くのレポートリレーショナルデータベースおよびデータウェアハウスは、大量の抽出、変換、読み込み(ETL)バッチ更新を使用するため、参照整合性を適用することが困難または不可能になり、SQLクエリの作成者が変更できない潜在的にNULLの結合列が生成され、内部結合が省略されます。エラーの兆候のないデータ。内部結合を使用するかどうかは、データベースの設計とデータの特性によって異なります。 1つのテーブルの結合列にNULL値が含まれている可能性がある場合、通常、左外部結合を内部結合の代わりに使用できます。
NULL(空)の可能性があるデータ列をリンクとして使用しないでください。意図した結果がNULL値の行を削除することでない限り、内部結合。 NULL結合列を結果セットから意図的に削除する場合、テーブルの結合とフィルタリングは1つのステップで実行されるため、内部結合は外部結合よりも高速になる可能性があります。逆に、内部結合は、SQL Where句のデータベース関数と組み合わせて大量のクエリで使用すると、パフォーマンスが大幅に低下したり、サーバーがクラッシュしたりする可能性があります。 SQL Where句の関数を使用すると、データベースが比較的コンパクトなテーブルインデックスを無視する可能性があります。データベースは、計算値に依存するフィルターを使用して行数を減らす前に、両方のテーブルから選択した列を読み取り、内部結合する場合があります。その結果、処理が比較的大量になります。
結果セットの場合数値識別子コードの全文記述を検索するために使用されるマスターテーブル(ルックアップテーブル)を含むいくつかのテーブルを結合することによって生成されます。外部キーのいずれかでNULL値を指定すると、結果セットから行全体が削除される可能性があります。エラーの兆候はありません。 1つ以上の内部結合と複数の外部結合を含む複雑なSQLクエリでは、内部結合リンク列のNULL値に対して同じリスクがあります。
内部結合を含むSQLコードへのコミットメントでは、NULL結合列はベンダーの更新、設計変更、データ変換、移行、一括インポート、マージなどのアプリケーションのデータ検証ルール外の一括処理など、将来の変更によって導入されます。
内部結合をさらに次のように分類できます。等結合、自然結合、または相互結合として。
Equi-joinEdit
等結合は、等価比較のみを使用する特定のタイプのコンパレータベースの結合です。結合述語内。他の比較演算子(<
など)を使用すると、結合は等結合として不適格になります。上記のクエリは、等結合の例をすでに提供しています。
SELECT *FROM employee JOIN department ON employee.DepartmentID = department.DepartmentID;
次のように等結合を記述できます。
SELECT *FROM employee, departmentWHERE employee.DepartmentID = department.DepartmentID;
共同の場合等結合のlumnは同じ名前であり、SQL-92は、USING
構文を使用して、等結合を表現するためのオプションの省略表記を提供します。
SELECT *FROM employee INNER JOIN department USING (DepartmentID);
USING
構造は単なる構文糖衣構文ではありませんが、結果セットが結果と異なるためです。明示的な述語を持つバージョンのセット。具体的には、USING
リストに記載されている列は、結合内のテーブルごとに1回ではなく、非修飾名で1回だけ表示されます。上記の場合、DepartmentID
列は1つで、employee.DepartmentID
またはdepartment.DepartmentID
はありません。 。
USING
句はMSSQLServerおよびSybaseではサポートされていません。
ナチュラルjoinEdit
ナチュラルjoinは、equi-joinの特殊なケースです。自然結合(⋈)は、(R⋈S)として記述される二項演算子です。ここで、RとSは関係です。自然結合の結果は、共通の属性名が等しいRとSのタプルのすべての組み合わせのセットです。例として、テーブルEmployeeとDept、およびそれらの自然結合について考えてみます。
|
|
|
これは、リレーションの構成を定義するためにも使用できます。たとえば、EmployeeとDeptの構成は、上記のようにそれらの結合であり、共通属性DeptNameを除くすべてに投影されます。圏論では、結合は正確にファイバー製品です。
自然結合は論理積のリレーショナル対応物であるため、間違いなく最も重要な演算子の1つです。 ANDで接続されている2つの述語のそれぞれに同じ変数が現れる場合、その変数は同じものを表し、両方の出現は常に同じ値で置き換える必要があることに注意してください。特に、自然結合により、外部キーによって関連付けられた関係の組み合わせが可能になります。たとえば、上記の例では、外部キーがEmployee.DeptNameからDept.DeptNameに保持されている可能性があり、EmployeeとDeptの自然結合により、すべての従業員とその部門が結合されます。これは、外部キーが同じ名前の属性間で保持されるために機能します。 Dept.managerからEmployee.Nameへの外部キーなど、これが当てはまらない場合は、自然結合を行う前に、これらの列の名前を変更する必要があります。このような結合は、等結合と呼ばれることもあります。
より正式には、自然結合のセマンティクスは次のように定義されます。
R⋈S= {t∪s∣t∈R ∧s∈S∧Fun(t∪s)} {\ displaystyle R \ bowtie S = \ left \ {t \ cup s \ mid t \ in R \ \ land \ s \ in S \ \ land \ {\ mathit {Fun}}(t \ cup s)\ right \}}、
ここで、Funは、rが関数である場合に限り、リレーションrに当てはまる述語です。通常、RとSには少なくとも1つの共通属性が必要ですが、この制約を省略し、RとSに共通属性がない場合、自然結合は正確にデカルト積になります。
自然結合は、次のようにCoddのプリミティブを使用してシミュレートできます。c1、…、cmをRとSに共通の属性名、r1、…、rnをRに固有の属性名、s1、…、skをSに固有の属性。さらに、属性名x1、…、xmがRにもSにも存在しないと仮定します。最初のステップで、Sの共通属性名の名前を変更できます。
T =ρx1/ c 1、…、xm / cm(S)=ρx1/ c 1(ρx2/ c 2(…ρxm/ cm(S)…)){\ displaystyle T = \ rho _ {x_ {1} / c_ {1}、\ ldots、x_ {m} / c_ {m}}(S)= \ rho _ {x_ {1} / c_ {1}}(\ rho _ {x_ {2} / c_ {2 }}(\ ldots \ rho _ {x_ {m} / c_ {m}}(S)\ ldots))}
次に、デカルト積を取得して、結合するタプルを選択します。
U =πr1、…、rn、c 1、…、cm、s 1、…、sk(P){\ displaystyle U = \ pi _ {r_ {1}、 \ ldots、r_ {n}、c_ {1}、\ ldots、c_ {m}、s_ {1}、\ ldots、s_ {k}}(P)}
自然結合は、等式の一種です。結合されたテーブルで同じ列名を持つ両方のテーブルのすべての列を比較することにより、結合述語が暗黙的に発生する結合。結果の結合テーブルには、同じ名前の列のペアごとに1つの列のみが含まれます。同じ名前の列が見つからない場合、結果は相互結合になります。
ほとんどの専門家は、NATURAL JOINは危険であるため、使用を強く推奨しないことに同意しています。危険は、他のテーブルの別の列と同じ名前の新しい列を誤って追加することから発生します。次に、既存の自然結合が「自然に」新しい列を比較に使用し、以前とは異なる基準(異なる列から)を使用して比較/一致を行う場合があります。したがって、テーブル内のデータが変更されておらず、拡張されているだけであっても、既存のクエリは異なる結果を生成する可能性があります。テーブルリンクを自動的に決定するために列名を使用することは、命名規則に非現実的な制約を課す数百または数千のテーブルを持つ大規模なデータベースではオプションではありません。実世界のデータベースは通常、ビジネスルールとコンテキストのために、一貫して入力されない(NULL値が許可される)外部キーデータを使用して設計されます。異なるテーブル内の同様のデータの列名を変更するのが一般的な方法であり、この厳密な一貫性の欠如により、自然結合が議論の理論的概念に委ねられます。
上記の内部結合のサンプルクエリは、自然結合として表現できます。次の方法で結合します。
SELECT *FROM employee NATURAL JOIN department;
明示的なUSING
句と同様に、結合されたテーブルには、修飾子なしでDepartmentID列が1つだけ表示されます:
DepartmentID | Employee.LastName | Department.DepartmentName |
---|---|---|
34 | Smith | Clerical |
33 | ジョーンズ | エンジニアリング |
34 | ロビンソン | クレリカル |
33 | ハイゼンベルグ | エンジニアリング |
31 | ラファティ | 販売 |
PostgreSQL、MySQL、Oracle su自然結合をサポートします。 MicrosoftT-SQLとIBMDB2はそうではありません。結合で使用される列は暗黙的であるため、結合コードはどの列が予期されているかを示しておらず、列名を変更すると結果が変わる可能性があります。 SQL:2011標準では、自然結合はオプションのF401「拡張結合テーブル」パッケージの一部です。
多くのデータベース環境では、列名はクエリ開発者ではなく外部ベンダーによって制御されます。自然結合は、ベンダーが義務付けたバージョンのアップグレード中に変更される可能性のある列名の安定性と一貫性を前提としています。