首页 > 解决方案 > 查询之间的区别

问题描述

我有三个表

TAB01

坎普1 | 坎普2
 01 |一个
 02 |二
 03 |三
 04 |四

TAB02

坎普1 | 坎普2
 01 |一个
 02 |二
 03 |三

TAB03

坎普1 | 坎普2
 01 |一个
 02 |二
 03 |三

当我执行查询时

SELECT TAB01.CAMPO1,TAB02.CAMPO2
FROM TAB01
  LEFT JOIN TAB02 ON TAB02.CAMPO1=TAB01.CAMPO1
  INNER JOIN TAB03 ON TAB03.CAMPO1=TAB02.CAMPO1

结果是

坎普1 | 坎普2
 01|01
 02|02
 03|03

当我执行查询时

SELECT TAB01.CAMPO1,T1.CAMPO2
FROM TAB01
  LEFT JOIN (SELECT TAB02.CAMPO1,TAB02.CAMPO2 FROM_TAB02 
  INNER JOIN TAB03 ON TAB03.CAMPO1=TAB02.CAMPO1) T1 ON T1.CAMPO1=TAB01.CAMPO1

结果是

坎普1 | 坎普2
01|01
02|02
03|03
04|空

为什么?

不应该一样吗?

标签: sql

解决方案


您的两个查询是:

SELECT TAB01.CAMPO1, TAB02.CAMPO2
FROM TAB01 LEFT JOIN 
     TAB02 ON
     TAB02.CAMPO1 = TAB01.CAMPO1 INNER JOIN 
     TAB03
     ON TAB03.CAMPO1 = TAB02.CAMPO1

SELECT TAB01.CAMPO1, T1.CAMPO2
FROM TAB01 LEFT JOIN
     (SELECT TAB02.CAMPO1,TAB02.CAMPO2
      FROM_TAB02 INNER JOIN
           TAB03
           ON TAB03.CAMPO1 = TAB02.CAMPO1
     ) T23  -- changed the alias to something more reasonable
     ON T23.CAMPO1 = TAB01.CAMPO1

这些在结果集中的行方面完全不同。

对于第一个查询,逻辑是:

  • TAB01即使 . 中没有匹配项,也要保留所有行TAB02
  • 然后最终结果集只有行 whereTAB02TAB03match。
  • 因为NULLs不匹配最终INNER JOIN条件,所以查询本质上都是INNER JOINs。

第二个查询的逻辑是:

  • TAB01即使 . 中没有匹配项,也要保留所有行T23
  • 加入TAB02TAB03因此只有匹配的行。

上没有额外的过滤TAB01

作为外部连接的一般规则,我建议:

  • INNER JOIN如果有的话,首先使用s。这些可以过滤数据。
  • 然后使用LEFT JOINs 保留前面一个或多个表中的所有行。
  • 一旦使用LEFT JOIN,请勿使用INNER JOINRIGHT JOIN

FULL JOINs 很少需要。而且我几乎从不使用RIGHT JOINs。


推荐阅读