当前位置: 首页 > 面试题库 >

SQL左联接与FROM行上的多个表?

佟和平
2023-03-14
问题内容

大多数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,因此,当涉及到Employee的INNER
JOIN时,就无法满足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%'

这个额外的子句用于连接,但不是整个行的过滤器。因此,该行可能与公司信息一起出现,但是该行的所有部门和雇员列中都可能为NULL,因为该公司的名称中没有任何部门带有X。使用旧语法很难做到这一点。

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

此外,通过在查询优化器中抛出一堆表以及一堆WHERE子句的旧方法类似于说“在这里,尽力而为”。使用新的语法,查询优化器只需很少的工作就可以确定哪些部分组合在一起。

所以你有它。

LEFT和INNER JOIN是未来的潮流。



 类似资料:
  • 问题内容: 我在SQL中有此查询,并且希望它使用Entity Framework 在LINQ中实现它,但是如何应用左外部联接的多个表? 问题答案: 这是使用LINQ实现左外部联接的方式。您应该使用GroupJoin(语法): 该查询联接了三个表。您可以以相同的方式加入其余表。

  • 问题内容: 我用多个(包括一个)编写了这个SQL请求。 它给了我预期的结果 。 但是,“ Id就像此请求的Linq等效项一样,将其放在应用程序的数据访问层中。 我尝试了类似的东西: 我试图适应这个问题,但我无法弄清楚。我对分组子请求的内部迷失了。 谁能解释我哪里错了? 专家提示:如果有人可以用lambda表达式编写等效项,则可获赠积分 问题答案: 要将SQL转换为LINQ查询理解: 将子选择转换为

  • 问题内容: 我正在使用SQL Server(我相信是2005)。 我有2列和439行(每行都是唯一的)。 我有35列和数十万行(每行也是唯一的)。 每行都有每小时的观察和其他一些房屋管理信息。现在出于测试目的,我仅对今天的日期(即2013年4月19日)感兴趣。 如果我做: 我得到10526,这是正确的,因为每天有10526个不同的位置,每小时都有观测数据。 我想左连接TableA和TableB ,

  • 我是(My)SQL的新手,需要一些帮助:在数据库中,我有3个表,一个例子: 购买: 制造者: 型号: 在表purchases中,model是一个外键,它链接到model.id。在模型中,“制造商”是一个外键,它与“制造商id”相链接。 我的目标是一个如下图所示的表格: 我知道如何在表购买中加入以获取型号的名称。不幸的是,我不知道如何获取制造商? 我的SQL-查询:

  • 问题内容: 我想添加代表其他表计数的列。 我有3张桌子。 留言内容 主题 星星_吉文 我要结束于: Topic_Review 因此,基本上我想在3列中附加唯一值的计数(每个主题中给定的星数,在主题中具有消息的唯一用户以及每个主题中的唯一消息数)。 我希望最终也能够过滤类别(在两列中均可见)。 此外,我最终希望按加入的人数进行排序。例如,我将要有一个按钮,该按钮按升序按“星数”排序,或按降序按“用户

  • 我想添加表示来自其他表的计数的列。 我有三张桌子。 消息 主题 STARS_GIVED 我想以: 主题回顾 所以基本上,我想附上3列唯一值的计数(每个主题中给出的星数,在主题中有消息的唯一用户,以及每个主题中唯一消息的数量)。 我希望最终能够对类别进行筛选(看看两列)。 此外,我希望最终按我加入的计数排序。例如,我将有一个按钮,按“星星的数目”按升序排序,或按“用户的数目”按降序排序,等等。 我试