SQL:JOIN 还是 LEFT OUTER JOIN?

SQL: JOIN vs LEFT OUTER JOIN?

我有多个 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'

例如。使用 LEFT OUTER JOIN

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

两者完全等价,因为WHERE子句将LEFT JOIN变成了INNER JOIN

当在 LEFT JOIN 中过滤除 first table 以外的所有条件时,条件通常应在 ON 子句中。据推测,你也有一个有效的连接条件,连接两个 tables:

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 版本不同,因为此版本 returns 所有用户 甚至没有待付款的用户。

如上所述:

JOIN is synonym of INNER JOIN. It's definitively different from all types of OUTER JOIN

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

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

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

您的问题的简短回答是:

  • 比 link 两个相关表更喜欢 JOIN(又名“INNER JOIN”)。实际上,大多数时候您会使用 INNER JOIN。
  • INNER JOIN 是两个表的交集。它由上面维恩图中间的“绿色”部分表示。
  • 当您需要左侧、右侧或两个外部区域时,请使用“外部连接”。
  • 在您的示例中,结果集恰好相同:两个表达式恰好等价。
  • 此外:请务必熟悉 RDBMS 的“显示计划”(或同等内容):https://www.sqlshack.com/execution-plans-in-sql-server/

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

首先是理论:

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

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

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

假设我们必须对某个谓词 p

执行 R JOIN S(和 R LEFT JOIN S)

J = R JOIN S on (p)

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

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

这个结果是左连接:

R 左连接 S (p)

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

回到你的问题:

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

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

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

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

比如我用的是微软的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'