是否需要正确的加入?

时间:2008-10-29 20:13:19

标签: sql

是否存在任何需要RIGHT JOIN的查询,或者是否可以使用LEFT JOIN重写它们?

更具体地说,如果没有正确的连接,你如何重写这个(我猜是没有任何子查询或其他幻想):


SELECT *
FROM t1
LEFT JOIN t2 ON t1.k2 = t2.k2
RIGHT JOIN t3 ON t3.k3 = t2.k3

7 个答案:

答案 0 :(得分:23)

您可以随时重新编写它们以获得相同的结果集。但是,有时执行计划可能在重要方面(性能)有所不同,有时正确的连接让您以更有意义的方式表达查询。

让我来说明性能差异。程序员倾向于根据一次发生的sql语句来思考。但是,通过一系列步骤保持一个复杂查询的心智模型是有用的,其中表通常以列出的顺序连接。所以你可能有这样的查询:

SELECT * /* example: don't care what's returned */
FROM LargeTable L
LEFT JOIN MediumTable M ON M.L_ID=L.ID
LEFT JOIN SmallTable S ON S.M_ID=M.ID
WHERE ...

服务器通常会先将WHERE子句中的任何内容应用到列出的第一个表(在本例中为LargeTable),以减少加载到内存中所需的内容。然后它将加入下一个表(MediumTable),然后加入那个表(SmallTable),依此类推。

我们想要做的是使用一种策略来解释每个联接表对结果的预期影响。通常,您希望尽可能长地保持结果集尽可能小。将该原则应用于上面的示例查询,我们发现它显然比它需要的慢得多。它从较大的集合(表格)开始并向下运行。我们想从较小的集开始并开始工作。这意味着首先使用SmallTable,这样做的方法是通过RIGHT JOIN。

这里的另一个关键是服务器通常无法知道在连接完成之前需要哪些来自SmallTable的行。因此,只有SmallTable比LargeTable小得多才能将整个SmallTable加载到内存中比从LargeTable开始的任何东西都要便宜(LargeTable是一个大表,可能是索引良好的,可能是在一个或三个字段上过滤在where子句中。

重要的是还要指出,在绝大多数情况下,优化器会查看这个并以最有效的方式处理事情,并且大多数情况下优化器会比这更好地完成这项工作。可以。

但优化器并不完美。有时你需要帮助它:特别是如果你的一个或多个“表”是一个视图(可能是一个链接服务器!)或一个嵌套的select语句,例如。嵌套子查询也是一个很好的例子,您可能希望使用正确的联接以表达原因:它允许您移动查询的嵌套部分,以便您可以更好地分组。

答案 1 :(得分:12)

您始终只能使用左连接...

SELECT * FROM t1
    LEFT JOIN t2 ON t1.k2 = t2.k2
    RIGHT JOIN t3 ON t3.k3 = t2.k3

等同于:

Select * From t3 
   Left Join (t1 Left Join t2 
                  On t2.k2 = t1.k2)
      On T2.k3 = T3.K3

一般情况下,我总是尝试只使用左连接,因为左连接中左边的表是输出中包含行的ALL,我喜欢这样想,(左侧)为“基础”设置我正在执行cartesion产品(加入)...所以我喜欢在SQL中首先使用...

答案 2 :(得分:8)

是的!每时每刻! (不得不承认,主要是在你严格要求首先打电话的时候使用)

关于这个主题:here's a nice visual guide on joins

答案 3 :(得分:6)

这有点像询问是否需要使用大于号。使用更适合手头任务的那个。

答案 4 :(得分:1)

您可以随时交换表格顺序,将右边连接转换为LEFT JOIN。有时,以某种方式做到这一点会更有效率。

答案 5 :(得分:-1)

我使用LEFT JOIN大约99.999%的时间,但我的一些动态代码生成使用RIGHT JOIN s,这意味着连接之外的东西不需要反转。

我还想补充一点,你给我的相信的具体例子会产生交叉连接,这可能不是你的意图,甚至不是一个好的设计。

即。我认为它实际上与:

相同
SELECT *
FROM t1
CROSS JOIN t3
LEFT JOIN t2
    ON t1.k2 = t2.k2
    AND t3.k3 = t2.k3

而且,因为它是一个交叉连接,优化器将无法做很多事情。

答案 6 :(得分:-2)

许多编程语言中有许多元素并非严格要求才能获得正确的结果,但允许一个a)更清楚地表达意图b)以提高性能。示例包括数字,字符,循环,开关,类,联接,类型,过滤器以及数千个。