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

很显然,当你需要一个外连接时,第二个语法是必需的。 但是当做一个内连接时,为什么我应该更喜欢第二种语法(或反之)?


在大多数现代数据库中,旧语法只列出表格,并使用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,因此,当涉及到INNER JOIN到Employee时,无法为Employee行实现该约束,因此它不会出现。

另一方面,如果查询优化器决定首先解决部门 - 员工加入,然后与公司左键加入,则会看到它们。

所以旧的语法是不明确的。 没有办法指定你想要的,而不处理查询提示,而且一些数据库根本没有办法。

输入新的语法,您可以选择此语法。

例如,如果你想要所有公司,如问题描述所述,这就是你要写的东西:

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

您在此指定要将部门 - 员工连接作为一个连接完成,然后将这些连接的结果留给公司。

另外,假设您只想要名称中包含字母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. 旧的语法很难。

这就是为什么在其他供应商中,自从SQL Server 2005及更高版本以来,Microsoft已弃用旧的外部连接语法,而不是旧的内部连接语法。 使用旧式外连接语法与运行在Microsoft SQL Server 2005或2008上的数据库交谈的唯一方法是以8.0兼容模式(又名SQL Server 2000)设置该数据库。

另外,旧的方式,通过在查询优化器中抛出一堆表,并附带一堆WHERE子句,就好像在说“在这里,尽你最大的努力”。 使用新的语法,查询优化器为了找出哪些部分结合在一起所做的工作量较少。

所以你有它。

LEFT和INNER JOIN是未来的潮流。


JOIN语法保持它们所应用的表格附近的条件。 这在加入大量表格时尤其有用。

顺便说一下,你也可以用第一种语法做外连接:

WHERE a.x = b.x(+)

要么

WHERE a.x *= b.x

要么

WHERE a.x = b.x or a.x not in (select x from b)

第一种方法是旧标准。 第二种方法是在SQL-92中引入的,http://en.wikipedia.org/wiki/SQL。 完整的标准可以在http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt查看。

数据库公司采用SQL-92标准需要很多年。

所以第二种方法是首选的原因,它是根据ANSI和ISO标准委员会的SQL标准。

链接地址: http://www.djcxy.com/p/86259.html

上一篇: SQL left join vs multiple tables on FROM line?

下一篇: Difference between left join and right join in SQL Server