SQL左联接vs第行上的多个表?

SQL左联接vs第行上的多个表?,sql,syntax,join,Sql,Syntax,Join,大多数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 显然,当您需要外部联接时,需要第二种语法。但是当进行内部连接时,为什么我更喜欢第二种语法而不是第一种语法(反之亦然)?我听到很多人抱怨第一种语法太难理解,而且不清楚。我看不出有什么问题,但在讨论之后,为了清晰起见,我甚至在内部联接上使用了第二个 对于数据库来说,

大多数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 a.x = b.x(+)


第一个和第二个查询可能会产生不同的结果,因为左连接包括第一个表中的所有记录,即使右表中没有相应的记录。

当需要外部连接时,第二个语法是而不是始终需要:

甲骨文:

SELECT a.foo, b.foo
  FROM a, b
 WHERE a.x = b.x(+)
MSSQLServer(尽管它是2000版)/Sybase:


回到你的问题上来。我不知道答案,但这可能与以下事实有关:连接更自然(至少在语法上)与在执行以下操作时向where子句中添加表达式相比:加入第二种方法更可取,因为它不太可能由于忘记放入where子句而导致意外交叉加入。没有on子句的联接将无法通过语法检查,没有where子句的旧式联接不会失败,它将执行交叉联接

此外,当您以后不得不使用左联接时,它们都位于同一结构中对维护很有帮助。旧的语法自1992年以来已经过时了,现在是停止使用它的时候了


此外,我还发现,许多只使用第一种语法的人并不真正理解联接,而理解联接对于在查询时获得正确结果至关重要。

基本上,当FROM子句列出如下表时:

SELECT * FROM
  tableA, tableB, tableC
结果是表a、B、C中所有行的叉积。然后应用限制
,其中tableA.id=tableB.a_id
,这将丢弃大量行,然后进一步
和tableB.id=tableC.b_id
然后您应该只获得您真正感兴趣的行

DBMS知道如何优化此SQL,从而使使用联接编写此SQL的性能差异可以忽略不计(如果有)。使用联接表示法使SQL语句更具可读性(IMHO,不使用联接会使语句变得一团糟)。使用叉积,您需要在WHERE子句中提供连接条件,这就是符号的问题所在。你把WHERE子句挤满了像这样的东西

    tableA.id = tableB.a_id 
AND tableB.id = tableC.b_id 

仅用于限制交叉积。WHERE子句应仅包含对结果集的限制。如果将表联接条件与结果集限制混合使用,您(和其他人)会发现查询更难阅读。您应该明确使用联接,并保持FROM子句a FROM子句和WHERE子句a WHERE子句。

对于一些表来说,
SELECT*FROM table1、table2、
语法是可以的,但随着表数目的增加,它变得越来越难以读取(不一定是数学上精确的语句)

连接语法(在开始时)更难编写,但它明确了哪些条件会影响哪些表。这使得犯错误更加困难


此外,如果所有联接都是内部联接,则两个版本都是等效的。然而,当您在语句中的任何位置有一个外部联接时,事情就会变得复杂得多,这实际上保证了您编写的内容不会查询您认为您编写的内容。

旧语法,只列出表,并使用
WHERE
子句指定联接条件,在大多数现代数据库中被弃用

这不仅仅是为了展示,当您在同一个查询中同时使用内部联接和外部联接时,旧语法可能存在歧义

让我给你举个例子

假设系统中有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,因此当涉及到员工的内部连接时,没有w
    tableA.id = tableB.a_id 
AND tableB.id = tableC.b_id 
Company
Department
Employee
SELECT * -- for simplicity
FROM Company, Department, Employee
WHERE Company.ID *= Department.CompanyID
  AND Department.ID = Employee.DepartmentID
SELECT *
FROM Company
     LEFT JOIN (
         Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
     ) ON Company.ID = Department.CompanyID
SELECT *
FROM Company
     LEFT JOIN (
         Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
     ) ON Company.ID = Department.CompanyID AND Department.Name LIKE '%X%'