【问题标题】:SQL: JOIN vs LEFT OUTER JOIN?SQL:连接与左外连接?
【发布时间】:2021-09-02 14:38:34
【问题描述】:

我有多个看起来相似的 SQL 查询,其中一个使用 JOIN,另一个使用 LEFT OUTER JOIN。我玩弄了 SQL,发现它返回了相同的结果。代码库可互换地使用 JOIN 和 LEFT OUTER JOIN。虽然LEFT JOIN 似乎可以与LEFT OUTER JOIN 互换,但我似乎找不到任何关于JOIN 的信息。这是好的做法吗?

Ex Query1 使用 JOIN

SQL
SELECT 
   id,
   name 
FROM 
   u_users customers
JOIN 
   t_orders orders
ON orders.status=='PAYMENT PENDING'

例如。 Query2 使用 LEFT OUTER JOIN

SQL
SELECT 
   id,
   name 
FROM 
   u_users customers
LEFT OUTER JOIN 
   t_orders orders
ON orders.status=='PAYMENT PENDING'

【问题讨论】:

标签: sql join left-join


【解决方案1】:

首先是理论:

连接是左连接的子集(所有其他条件相同)。在某些情况下它们是相同的

不同之处在于左连接将包括左侧关系中的所有元组(即使它们不匹配连接谓词),而连接将仅包括左侧与谓词。

例如假设我们必须关系 R 和 S。

假设我们必须对某个谓词 p 执行 R JOIN S(和 R LEFT JOIN S)

J = R JOIN S on (p)

现在,找出 R 中不在 J 中的元组。

最后,将这些元组添加到 J(将 J 中不在 R 中的任何属性填充为 null)

这个结果是左连接:

R 左连接 S (p)

所以当关系左侧的所有元组都在JOIN中时,这个结果将与Left Join相同。

回到你的问题:

您的 JOIN 很可能包含来自用户的所有元组。因此,如果使用 JOIN 或 LEFT JOIN,查询是相同的。

【讨论】:

    【解决方案2】:

    两者都是一样的,这里没有区别。

    使用 Join 时需要使用 ON 子句。当您不使用 ON 子句时,它可以匹配两个表之间的任何数据。 这可能会导致性能问题以及映射不需要的数据。

    如果您想查看差异,可以使用“执行计划”

    例如,我使用 Microsoft AdventureWorks 数据库作为示例。

    左外连接:

    左连接:

    如果您在编写时使用 ON 子句,则可能会出现循环。 示例“执行计划”如下。

    您可以使用 ON 子句补充访问正确的映射和数据。

    select 
       id,
       name 
    from 
       u_users customers
    left outer join 
       t_orders orders on customers.id = orders.userid
    where orders.status=='payment pending'
    

    【讨论】:

    • 那些伪维恩图通常像病毒一样传播,但它们没有帮助。圆圈的元素代表什么?什么是圆圈?你不说。它们不是 A 和 B。它们不是 SQL 表,因为它们是包而不是集合。给出一个正确的传说是极其困难的。您的特定版本不处理运营商的一般情况。 Venn Diagram for Natural Join PS 这个问题中的问题是几十年前的重复问题。 How to Answerhelp center
    • LEFT JOIN 返回由 NULL 扩展的 INNER JOIN 行 UNION ALL 不匹配的左表行。作为 OUTER JOIN 的一部分,始终知道您想要什么 INNER JOIN。在 LEFT JOIN 之后,需要右 [sic] 表列不为 NULL 的 WHERE、INNER JOIN 或 HAVING 删除任何引入了 NULL 的行,即只留下 INNER JOIN 行,即“将 OUTER JOIN 转换为 INNER JOIN”。你有那个。 PS这是一个常见问题。
    【解决方案3】:

    如前所述:

    JOIN 是 INNER JOIN 的同义词。它绝对不同于所有 OUTER JOIN 的类型

    所以问题是“我什么时候应该使用外连接?”

    这是一篇很好的文章,有几个很棒的图表:

    https://www.sqlshack.com/sql-outer-join-overview-and-examples/

    您的问题的简短回答是:

    • 首选 JOIN(又名“INNER JOIN”)来链接两个相关的表。在实践中,您大部分时间都会使用 INNER JOIN。
    • INNER JOIN 是两个表的交集。它由上面维恩图中间的“绿色”部分表示。
    • 如果需要左侧、右侧或两个外部区域,请使用“外部连接”。
    • 在您的示例中,结果集恰好相同:两个表达式恰好相等。
    • 另外:请务必熟悉 RDBMS 的“显示计划”(或等效项):https://www.sqlshack.com/execution-plans-in-sql-server/

    '希望对您有所帮助...

    【讨论】:

    • 这种伪维恩图具有误导性和无益,正确的图例很复杂。例如,表是袋子而不是集合,圆圈不是输入表,但它们是这样标记的。同样在这种情况下,子圈区域上的文字也不清楚。请参阅我对另一个答案的评论。
    【解决方案4】:

    两者完全相同,因为WHERE 子句将LEFT JOIN 转换为INNER JOIN

    当过滤LEFT JOIN 中除first 表之外的所有表时,条件通常应位于ON 子句中。大概,你也有一个有效的连接条件,连接两个表:

    SELEC id, name 
    FROM u_users u LEFT JOIN 
         t_orders o
         ON o.user_id = u.user_id AND o.status = 'PAYMENT PENDING';
    

    此版本与INNER JOIN 版本不同,因为此版本返回所有用户,即使是那些没有待付款的用户。

    【讨论】:

    • where 是否总是将左连接更改为内连接?根据其他 cmets,由于我的示例,结果集恰好是相同的。但在我的代码库中,表格更大/更复杂,查询复杂,因此很难证明这是否是正确答案
    • @DawnAxolotl 。 . .不总是。但除了第一个表之外,几乎所有的比较都可以。
    猜你喜欢
    • 2011-10-01
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多