内部結合を使用する
T-SQL クエリで最も頻繁に発生する JOIN の種類は、INNER JOIN です。 内部結合は、特に高度に正規化されたデータベース環境で、多くの一般的なビジネス上の問題を解決するために使用されます。 複数のテーブルに格納されているデータを取得するには、多くの場合、INNER JOIN クエリを使用して結合する必要があります。 INNER JOIN では、論理処理フェーズがデカルト積として開始されてから、述語に一致しないすべての行が削除されます。
INNER JOIN の処理
ここでは、SQL Server によって JOIN クエリが論理的に処理される手順について説明します。 わかりやすくするために、次の仮定の例には行番号が追加されています。
1) SELECT emp.FirstName, ord.Amount
2) FROM HR.Employee AS emp
3) JOIN Sales.SalesOrder AS ord
4) ON emp.EmployeeID = ord.EmployeeID;
ご存知のように、FROM 句は SELECT 句の前に処理されます。 2 行目から始まる処理を追跡してみましょう。
- FROM 句により、入力テーブルの 1 つとして HR.Employee テーブルが指定され、エイリアス emp が指定されます。
- 3 行目の JOIN 演算子は INNER JOIN (T-SQL の既定の型) の使用を反映しており、これにより、エイリアスが ord であるもう 1 つの入力テーブルとして Sales.SalesOrder が指定されます。
- SQL Server により、これらのテーブルに対して論理デカルト結合が実行され、結果が仮想テーブルとして次のステップに渡されます (クエリの物理的な処理では、オプティマイザーの決定に応じて、デカルト積演算が実際には実行されない場合があります。ただし、デカルト積が生成されると想定すると便利です)。
- SQL Server により、ON 句を使用して仮想テーブルがフィルター処理され、emp テーブルの EmployeeID 値が ord テーブルの EmployeeID と一致する行のみが保持されます。
- 残りの行は仮想テーブルに残され、SELECT ステートメントの次のステップに渡されます。 この例では、仮想テーブルは次に SELECT 句によって処理され、指定された 2 つの列がクライアント アプリケーションに返されます。
完了したクエリの結果は、従業員とその注文金額のリストです。 関連付けられた注文がない従業員は、HR.Employee テーブル内のエントリに対応しない EmployeeID を持つ注文と同様に、ON 句によってフィルターで除外されています。
INNER JOIN 構文
INNER JOIN は JOIN の既定の型であり、任意の INNER キーワードは JOIN 句で暗黙的です。 結合の種類を組み合わせるときは、次の仮定の例に示すように、結合の種類を明示的に指定すると便利です。
SELECT emp.FirstName, ord.Amount
FROM HR.Employee AS emp
INNER JOIN Sales.SalesOrder AS ord
ON emp.EmployeeID = ord.EmployeeID;
内部結合を使用してクエリを記述する場合は、次のガイドラインを考慮してください。
- テーブルのエイリアスは、SELECT リストだけでなく、ON 句を記述する場合にも推奨されます。
- 内部結合は、1 つの一致する列 (OrderID など)、または一致する複数の属性 (OrderID と ProductID の組み合わせなど) に対して実行できます。 一致する複数の列を指定する結合は、"複合" 結合と呼ばれます。
- INNER JOIN の FROM 句でテーブルがリストされる順序は、SQL Server オプティマイザーには関係ありません。 概念的には、結合は左から右に評価されます。
- FROM リスト内の結合されたテーブルのペアごとに 1 回、JOIN キーワードを使用します。 2 つのテーブルを使用するクエリでは、1 つの結合を指定します。 3 つのテーブルを使用するクエリでは、JOIN を 2 回使用します (最初の 2 つのテーブル間に 1 回。最初の 2 つのテーブル間の JOIN の出力と、3 番目のテーブルとの間にもう 1 回)。
INNER JOIN の例
次の仮定の例では、1 つの一致する列に対して結合を実行し、Production.Product テーブルの ProductModelID を Production.ProductModel テーブルの ProductModelID に関連付けます。
SELECT p.ProductID, m.Name AS Model, p.Name AS Product
FROM Production.Product AS p
INNER JOIN Production.ProductModel AS m
ON p.ProductModelID = m.ProductModelID
ORDER BY p.ProductID;
次の例では、3 つ以上のテーブルを含めるように内部結合を拡張する方法を示します。 Sales.SalesOrderDetail テーブルは、Production.Product と Production.ProductModel の間の JOIN の出力に結合されます。 JOIN と ON の各インスタンスにより、仮想出力テーブルの独自の設定とフィルター処理が行われます。 SQL Server クエリ オプティマイザーにより、結合とフィルター処理を実行する順序が決定されます。
SELECT od.SalesOrderID, m.Name AS Model, p.Name AS ProductName, od.OrderQty
FROM Production.Product AS p
INNER JOIN Production.ProductModel AS m
ON p.ProductModelID = m.ProductModelID
INNER JOIN Sales.SalesOrderDetail AS od
ON p.ProductID = od.ProductID
ORDER BY od.SalesOrderID;