首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

SQL 表連接全解析:內連接、外連接、交叉連接語法、類型、性能與最佳實踐

     編輯:關於SqlServer

連接語法標準演進

  • ANSI SQL-86:FROM a, b WHERE a.id = b.id(舊式,僅支持內連接)。
  • ANSI SQL-92:FROM a INNER JOIN b ON a.id = b.id(標準,支持內/外/交叉連接,推薦)。

兩者經優化器處理後執行計劃完全一致,差異在於可讀性、可維護性與外連接表達能力。

三大連接類型詳細解析

1. 內連接 —— 只返回匹配行

-- 等值連接(最常用)
SELECT a.*, b.OrderDate
FROM Customers a INNER JOIN Orders b ON a.CustomerID = b.CustomerID;

-- 自然連接:隱式去重公共列(SQL Server 不直接支持 NATURAL JOIN,需顯式列名)
SELECT a.CustomerID, a.CompanyName, b.OrderDate
FROM Customers a INNER JOIN Orders b ON a.CustomerID = b.CustomerID;

-- 不等連接:非 = 條件
SELECT e1.Name AS Emp1, e2.Name AS Emp2
FROM Employees e1 INNER JOIN Employees e2 ON e1.Salary > e2.Salary;

2. 外連接 —— 保留主表所有行

類型語法語義典型場景
左外連接LEFT [OUTER] JOIN保留左表所有行,右表無匹配則 NULL主表查明細(客戶-訂單、部門-員工)
右外連接RIGHT [OUTER] JOIN保留右表所有行,左表無匹配則 NULL少用,可改 LEFT 互換表順序
全外連接FULL [OUTER] JOIN保留兩表所有行,無匹配雙向 NULL雙向對賬、合併異構數據源
-- 左連接:所有客戶及其訂單(無訂單客戶也顯示)
SELECT c.CustomerID, c.CompanyName, o.OrderID, o.OrderDate
FROM Customers c LEFT JOIN Orders o ON c.CustomerID = o.CustomerID;

-- 全外連接:城市表與用戶表雙向對賬
SELECT c.CityName, u.UserName
FROM Cities c FULL OUTER JOIN Users u ON c.CityID = u.CityID;

3. 交叉連接 —— 笛卡爾積

-- 無 ON 條件,返回 M x N 行
SELECT t.Type, p.PubName
FROM Titles t CROSS JOIN Publishers p;
-- 6 類圖書 × 8 家出版社 = 48 行

⚠️ 極易產生海量結果集導致 OOM,僅用於受控小表組合(如生成日期維度、參數網格)。

自連接:表關聯自身

-- 員工-經理關係
SELECT e.Name AS Employee, m.Name AS Manager
FROM Employees e LEFT JOIN Employees m ON e.ManagerID = m.EmployeeID;

性能與優化建議

  1. 連接鍵建索引:被連接列(特別是大表側)必須有索引,否則 Hash Match/Table Scan 殺性能。
  2. 小表驅動大表:優化器通常選擇小表作 Build 輸入,但統計信息過期會誤判,及時 UPDATE STATISTICS。
  3. 避免隱式轉換:連接列類型不一致(如 VARCHAR vs NVARCHAR、INT vs BIGINT)導致掃描,統一類型或顯式 CAST。
  4. WHERE vs ON:外連接中,ON 決定如何匹配,WHERE 過濾最終結果。LEFT JOIN ... ON ... WHERE right.col = 'x' 會把外連接退化為內連接,條件應放在 ON 中。
  5. 使用表別名:簡潔、消除歧義、利於維護。

舊式 (+) 語法對照

ANSI-92Oracle (+) 兼容SQL Server 舊式
LEFT JOINWHERE a.id = b.id(+)WHERE a.id *= b.id (已棄用)
RIGHT JOINWHERE a.id(+) = b.idWHERE a.id =* b.id (已棄用)

現代開發統一使用 ANSI-92,跨平台遷移零改動。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved