使用內部聯結
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;
您應該已經知道,系統會在處理 SELECT 子句之前先處理 FROM 子句。 讓我們來追蹤處理進度,從第 2 行開始:
- FROM 子句會將 HR.Employee 資料表指定為其中一個輸入資料表,並給予其 emp 的別名。
- 第 3 行的 JOIN 運算子會反映 INNER JOIN (T-SQL 中的預設類型) 的使用,並將 Sales.SalesOrder 指定為另一個輸入資料表,其具有 ord 的別名。
- SQL Server 將會針對這些資料表執行邏輯笛卡兒聯結,並將結果以虛擬資料表的形式傳遞至下一個步驟。 (視最佳化工具的決策而定,查詢的實體處理可能不會實際執行笛卡兒乘積作業。但是假設要建立笛卡兒乘積很有幫助。)
- 透過使用 ON 子句,SQL Server 將會篩選虛擬資料表,並僅保留在 emp 資料表中的 EmployeeID 值符合 ord 資料表中 EmployeeID 的資料列。
- 剩餘的資料列會留在虛擬資料表中,並交給 SELECT 陳述式的下一個步驟。 在此範例中,虛擬資料表接著會由 SELECT 子句處理,而且會將兩個指定的資料行傳回至用戶端應用程式。
完成的查詢結果會是員工和其訂單數量的清單。 沒有任何相關聯訂單的員工都會由 ON 子句篩選掉;同樣地,EmployeeID 無法對應到 HR.Employee 資料表中任何項目的訂單也都會被篩選掉。
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 子句時也一樣。
- 內部聯結可以在單一相符資料行 (例如 OrderID) 或多個相符屬性 (例如 OrderID 和 ProductID 的組合) 上執行。 指定多個相符資料行的聯結稱為「複合」聯結。
- 在 FROM 子句中針對 INNER JOIN 列出資料表的順序,對於 SQL Server 最佳化工具來說並無任何影響。 就概念而言,聯結的評估順序是由左至右。
- 在 FROM 清單中,針對每一對已聯結資料表使用 JOIN 關鍵字一次。 針對雙資料表查詢,請指定單一聯結。 針對三資料表查詢,您將會使用 JOIN 兩次;一次是在前兩個資料表之間,另一次則是在前兩個資料表之間的 JOIN 輸出和第三個資料表之間。
INNER JOIN 範例
下列假設性範例會在單一相符資料行上執行聯結,將 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;
下一個範例會示範如何延伸內部聯結以包含超過兩個資料表。 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;