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

发布于 2024-10-13 10:57:28 字数 702 浏览 4 评论 0原文

我很好奇为什么我们需要使用 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

I'm curious as to why we need to use LEFT JOIN since we can use commas to select multiple tables.

What are the differences between LEFT JOIN and using commas to select multiple tables.

Which one is faster?

Here is my code:

   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

...and:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我家小可爱 2024-10-20 10:57:28

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

   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>

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

TABLEA INNER JOIN TABLEB ON <CONDITION>

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

CROSS JOIN 的 ANSI 标准生成 两个表之间的笛卡尔积

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

该语法的目的是将 TABLEA 中的每一行连接到 TABLEB 中的每一行。因此,A 中的 4 行和 B 中的 3 行产生 12 行输出。当与 WHERE 子句中的条件配对时,它有时会产生与 INNER JOIN 相同的行为,因为它们表达相同的事物(A 和 B 之间的条件 => keep 或 not)。然而,当您使用 INNER JOIN 而不是逗号时,阅读意图会更清楚。

从性能角度来看,大多数 DBMS 处理 LEFT 连接的速度比处理 INNER JOIN 的速度更快。逗号表示法可能会导致数据库系统误解其意图并产生错误的查询计划 - 因此这是 SQL92 表示法的另一个优点。

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

注意:

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

First of all, to be completely equivalent, the first query should have been written

   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

So that mw.* and nvs.* together produce the same set as the 2nd query's singular *. The query as you have written can use an INNER JOIN, since it includes a filter on nvs.correct.

The general form

TABLEA LEFT JOIN TABLEB ON <CONDITION>

attempts to find TableB records based on the condition. If the fails, the results from TABLEA are kept, with all the columns from TableB set to NULL. In contrast

TABLEA INNER JOIN TABLEB ON <CONDITION>

also attempts to find TableB records based on the condition. However, when fails, the particular record from TableA is removed from the output result set.

The ANSI standard for CROSS JOIN produces a Cartesian product between the two tables.

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

The intention of the syntax is that EACH row in TABLEA is joined to EACH row in TABLEB. So 4 rows in A and 3 rows in B produces 12 rows of output. When paired with conditions in the WHERE clause, it sometimes produces the same behaviour of the INNER JOIN, since they express the same thing (condition between A and B => keep or not). However, it is a lot clearer when reading as to the intention when you use INNER JOIN instead of commas.

Performance-wise, most DBMS will process a LEFT join faster than an INNER JOIN. The comma notation can cause database systems to misinterpret the intention and produce a bad query plan - so another plus for SQL92 notation.

Why do we need LEFT JOIN? If the explanation of LEFT JOIN above is still not enough (keep records in A without matches in B), then consider that to achieve the same, you would need a complex UNION between two sets using the old comma-notation to achieve the same effect. But as previously stated, this doesn't apply to your example, which is really an INNER JOIN hiding behind a LEFT JOIN.

Notes:

  • The RIGHT JOIN is the same as LEFT, except that it starts with TABLEB (right side) instead of A.
  • RIGHT and LEFT JOINS are both OUTER joins. The word OUTER is optional, i.e. it can be written as LEFT OUTER JOIN.
  • The third type of OUTER join is FULL OUTER join, but that is not discussed here.
白衬杉格子梦 2024-10-20 10:57:28

将 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

Separating the JOIN from the WHERE makes it easy to read, as the join logic cannot be confused with the WHERE conditions. It will also generally be faster as the server will not need to conduct two separate queries and combine the results.

The two examples you've given are not really equivalent, as you have included a sub-query in the first example. This is a better example:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文