SQL の左結合と FROM 行の複数テーブルの比較 質問する

SQL の左結合と FROM 行の複数テーブルの比較 質問する

ほとんどの SQL 方言は、次の両方のクエリを受け入れます。

SELECT a.foo, b.foo
FROM a, b
WHERE a.x = b.x

SELECT a.foo, b.foo
FROM a
LEFT JOIN b ON a.x = b.x

明らかに、外部結合が必要な場合は、2 番目の構文が必要です。しかし、内部結合を行う場合、なぜ最初の構文よりも 2 番目の構文を優先する必要があるのでしょうか (またはその逆)?

ベストアンサー1

テーブルをリストし、WHERE句を使用して結合条件を指定するだけの古い構文は、ほとんどの最新のデータベースでは非推奨になっています。

これは単なる表示ではなく、同じクエリで INNER 結合と OUTER 結合の両方を使用すると、古い構文ではあいまいになる可能性があります。

例を挙げてみましょう。

システムに 3 つのテーブルがあるとします。

Company
Department
Employee

各テーブルには、相互にリンクされた多数の行が含まれています。複数の会社があり、各会社には複数の部門があり、各部門には複数の従業員がいる場合があります。

さて、次に次のことを行います。

すべての会社を一覧表示し、その会社のすべての部門とすべての従業員を含めます。一部の会社にはまだ部門がありませんが、それらも必ず含めるようにしてください。従業員がいる部門のみを取得し、常にすべての会社を一覧表示するようにしてください。

だからこうします:

SELECT * -- for simplicity
FROM Company, Department, Employee
WHERE Company.ID *= Department.CompanyID
  AND Department.ID = Employee.DepartmentID

最後に、部門と人だけを必要とするという基準を満たすために、内部結合が行われていることに注意してください。

さて、それでは次に何が起こるでしょうか。問題は、データベース エンジン、クエリ オプティマイザー、インデックス、およびテーブル統計によって異なるということです。説明しましょう。

クエリ オプティマイザーが、これを行う方法として、まず会社を取得し、次に部門を検索し、最後に従業員との内部結合を実行することを決定した場合、部門のない会社は取得されません。

その理由は、句によって、行の個々の部分ではなく、最終結果に含まれるWHEREが決定されるためです。

この場合、左結合のため、Department.ID 列は NULL になり、Employee への INNER JOIN では、Employee 行の制約を満たす方法がないため、表示されません。

一方、クエリ オプティマイザーが最初に部門と従業員の結合に取り組み、次に会社との左結合を実行することにした場合、それらが表示されます。

したがって、古い構文はあいまいです。クエリヒントを扱わずに必要なものを指定する方法はありません。また、データベースによっては、まったく方法がないものもあります。

新しい構文を入力すると、選択できるようになります。

たとえば、問題の説明に記載されているように、すべての企業を取得したい場合は、次のように記述します。

SELECT *
FROM Company
     LEFT JOIN (
         Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
     ) ON Company.ID = Department.CompanyID

ここでは、部門と従業員の結合を 1 つの結合として実行し、その結果を会社と左結合することを指定します。

さらに、名前に文字 X を含む部門のみを取得したいとします。 繰り返しますが、古い形式の結合では、名前に X を含む部門がない場合、会社も失われるリスクがありますが、新しい構文では次のようにできます。

SELECT *
FROM Company
     LEFT JOIN (
         Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
     ) ON Company.ID = Department.CompanyID AND Department.Name LIKE '%X%'

この追加の句は結合に使用されますが、行全体のフィルターではありません。そのため、行には会社情報が表示されますが、その会社には名前に X が含まれる部門がないため、その行のすべての部門と従業員の列に NULL が含まれる可能性があります。これは、古い構文では困難です。

このため、他のベンダーと同様、Microsoft は SQL Server 2005 以降、古い外部結合構文を非推奨にしましたが、古い内部結合構文は非推奨にしていません。Microsoft SQL Server 2005 または 2008 で実行されているデータベースと、古いスタイルの外部結合構文を使用して通信する唯一の方法は、そのデータベースを 8.0 互換モード (別名 SQL Server 2000) に設定することです。

さらに、古い方法では、クエリ オプティマイザーに多数のテーブルと多数の WHERE 句を渡すというやり方は、「さあ、できる限りのことをしてください」と言っているようなものでした。新しい構文では、クエリ オプティマイザーがどの部分が組み合わさっているかを判断する作業が少なくなります。

というわけで、これで終わりです。

LEFT と INNER JOIN は未来の波です。

おすすめ記事