使用内部联接

已完成

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 子句将“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”表中条目不对应的订单的员工。

A Venn diagram showing the matching members of the Employee and SalesOrder sets

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 的组合)执行。 指定多个匹配列的联接称为复合联接。
  • 对于 SQL Server 优化器来说,INNER JOIN 的 FROM 子句中列出的表的顺序并不重要。 从概念上讲,联接将从左到右进行评估。
  • 对于 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;