0

如果我有几个LOJs 和几个,我应该使用INNER JOINS正确的标准句法结构吗?

示例场景

  • 5 个表 #A - #E 都有一个 UserId 列,每个表都有一个额外的度量列 - 表 #A 中的 MeasureA,表 #B 中的 MeasureB 等。
  • 表#A、#B、#C 都具有相同的一组 UserId
  • 表#D 和#E 在#A-#C 中具有不同的用户ID 子集。

这是要使用的正确结构吗:

SELECT 
    #A.UserId,
    #A.MeasureA,
    #B.MeasureB,
    #C.MeasureC,
    D = COALESCE(#D.MeasureD,0.),
    E = COALESCE(#E.MeasureE,0.)
FROM        
    #A
    JOIN #B
        ON #A.UserId = #B.UserId
    JOIN #C
        ON #A.UserId = #C.UserId
    LEFT OUTER JOIN #D
        ON #A.UserId = #D.UserId
    LEFT OUTER JOIN #E
        ON #A.UserId = #E.UserId

还是应该在#A 的子查询中应用 LOJ?

SELECT 
    X.UserId,
    X.MeasureA,
    #B.MeasureB,
    #C.MeasureC,
    X.D,
    X.E
FROM        
    (
    SELECT
      #A.UserId,
      #A.MeasureA,
      D = COALESCE(#D.MeasureD,0.),
      E = COALESCE(#E.MeasureE,0.)
    FROM #A 
        LEFT OUTER JOIN #D
            ON #A.UserId = #D.UserId
        LEFT OUTER JOIN #E
            ON #A.UserId = #E.UserId
    ) X
    JOIN #B
        ON X.UserId = #B.UserId
    JOIN #C
        ON X.UserId = #C.UserId
4

4 回答 4

2

当您使用左外连接时,目的是其中一个表保留其所有行,而不管其他表中的匹配情况如何。

我首选的结构是把这个表放在第一位:

select . . .
from <really important table> t left outer join
     . . .

如果您在子句后面有内部联接,这将不起作用from,因为这些会过滤掉没有匹配的行。

就您的查询而言,我认为第一个符合您的期望。第二个恰好做了你想做的事,因为你只是加入id列。但是结构非常危险。如果您的后续内部联接之一位于 的列上#E,那么它会(无意中)将左联接更改为内部联接。

因此,先放置内连接,然后再放置左外连接。

于 2014-01-31T18:22:41.377 回答
0

作为应用程序开发人员,我们信任框架,为什么我们不能信任 SQL 引擎来完成它的工作?第一种语法是 SQL 所期望的,不需要时不要使其复杂化。

但是,如果 A -> D 是一对多;A -> E 是一对多的,D​​ 和 E 之间没有关系。我会在将独立子查询中的 D 和 E 匹配行插回主查询之前对它进行 GROUP BY。

但是,这种做法似乎不适用于您的用例。

于 2014-01-31T18:52:49.813 回答
0

要记住的一件事是,除非您正在做一些非常时髦的事情,否则两个结构不同的等效查询可能会被优化器以相同的方式解释。您提出的两个查询几乎肯定是这种情况。

考虑到这一点,唯一“正确”的结构是您发现最容易阅读和维护的结构。就个人而言,我会选择第一个查询,因为它以直截了当的方式说明了它在做什么。


对于所提出的实际问题更明确一点:这里适用的标准不是 SQL 标准,而是编码标准:不要让事情变得比需要的更复杂。

于 2014-01-31T18:33:08.643 回答
-1

您可以在一个查询中完成所有操作,实际上无需使用子查询编写它。只需提醒一下 LOJ 的工作原理,您就会清楚地看到这一点!

于 2014-01-31T18:04:27.033 回答