左连接或使用逗号(,)从多个表中选择

时间:2011-01-24 06:18:09

标签: sql mysql query-optimization left-join

我很好奇为什么我们需要使用LEFT JOIN,因为我们可以使用逗号来选择多个表。

LEFT JOIN和使用逗号选择多个表之间有什么区别。

哪一个更快?

这是我的代码:

   SELECT mw.*, 
          nvs.* 
     FROM mst_words mw 
LEFT JOIN (SELECT no as nonvs, 
                  owner, 
                  owner_no, 
                  vocab_no, 
                  correct 
             FROM vocab_stats 
            WHERE owner = 1111) AS nvs ON mw.no = nvs.vocab_no 
    WHERE (nvs.correct > 0 ) 
      AND mw.level = 1

...和

SELECT * 
  FROM vocab_stats vs, 
       mst_words mw 
 WHERE mw.no = vs.vocab_no 
   AND vs.correct > 0 
   AND mw.level = 1 
   AND vs.owner = 1111

2 个答案:

答案 0 :(得分:4)

首先,要完全等效,应该编写第一个查询

   SELECT mw.*, 
          nvs.* 
     FROM mst_words mw 
LEFT JOIN (SELECT *
             FROM vocab_stats 
            WHERE owner = 1111) AS nvs ON mw.no = nvs.vocab_no 
    WHERE (nvs.correct > 0 ) 
      AND mw.level = 1

因此mw。*和nvs。*一起生成与第二个查询的单数*相同的集合。您编写的查询可以使用INNER JOIN,因为它包含nvs.correct上的过滤器。

一般表格

TABLEA LEFT JOIN TABLEB ON <CONDITION>

attempts 根据条件查找TableB记录。如果失败,则保留TABLEA的结果,并将TableB中的所有列设置为NULL。相比之下

TABLEA INNER JOIN TABLEB ON <CONDITION>

attempts 根据条件查找TableB记录。 但是,失败时,TableA中的特定记录将从输出结果集中删除。

CROSS JOIN的ANSI标准在两个表之间产生Cartesian product

TABLEA CROSS JOIN TABLEB
  -- # or in older syntax, simply using commas
TABLEA, TABLEB

语法的意图是TABLEA中的EACH行连接到TABLEB中的EACH行。因此A中的4行和B中的3行产生12行输出。当与WHERE子句中的条件配对时,它有时会产生INNER JOIN的相同行为,因为它们表达相同的事物(A和B之间的条件=&gt;保持与否)。但是,当您使用INNER JOIN而不是逗号时,在阅读意图时会更清楚。

在性能方面,大多数DBMS将比INNER JOIN更快地处理LEFT连接。逗号表示法可能会导致数据库系统误解意图并产生错误的查询计划 - 这是SQL92表示法的另一个优点。

为什么我们需要LEFT JOIN?如果上面的LEFT JOIN的解释仍然不够(将记录保存在B中没有匹配的B中),那么考虑到实现相同,你需要两个集合之间的复杂UNION使用旧的逗号表示法来实现相同的效果。 但如前所述,这不适用于您的示例,这实际上是隐藏在LEFT JOIN后面的INNER JOIN。

注意:

  • RIGHT JOIN与LEFT相同,只是它以TABLEB(右侧)而不是A开头。
  • RIGHT和LEFT JOINS都是OUTER连接。 OUTER一词是可选的,即它可以写成LEFT OUTER JOIN
  • 第三种类型的OUTER连接是FULL OUTER连接,但这里不讨论。

答案 1 :(得分:0)

将JOIN与WHERE分开使其易于阅读,因为连接逻辑不能与WHERE条件混淆。它通常也会更快,因为服务器不需要进行两个单独的查询并组合结果。

您给出的两个示例并不是真正等效的,因为您在第一个示例中包含了一个子查询。这是一个更好的例子:

SELECT vs.*, mw.*
FROM vocab_stats vs, mst_words mw
LEFT JOIN vocab_stats vs ON mw.no = vs.vocab_no
WHERE vs.correct > 0 
AND mw.level = 1
AND vs.owner = 1111