SQL Server:完全外部加入,开启与何处

时间:2015-05-07 15:20:41

标签: sql-server-2005 outer-join full-outer-join

我已经搜索过这个并且似乎无法找到答案。我提前道歉,因为我确定这个答案已经存在,但我似乎无法找到答案。

我正在使用SQL Server 2005数据库,并且我知道下面的查询并不代表规范化的数据库,因为numPlacements字段同时位于详细信息和汇总表中。我没有创建数据库。

下面的SQL给出了使用where子句时的预期结果。预期结果是两个表中缺少匹配值的所有行,或者这两个值不匹配。

但是,如果我注释where子句并取消注释ON子句中的最终AND,它将返回超过200k行而不是预期的120个结果。

SELECT CASE WHEN A.ID is NULL THEN B.ID ELSE A.ID END,
       A.numPlacements AS 'AnumPlacements', 
       B.numPlacements  AS 'bnumPlacements',
       B.numPlacements - A.numPlacements as 'Variance'
FROM   (SELECT ID,
               Sum(numPlacements) AS 'numPlacements' 
        FROM   PlacementDetailLevel
        GROUP  BY ID) A 
       FULL OUTER JOIN (SELECT ID,
                               Sum(numPlacements) AS 'numPlacements' 
                        FROM   PlacementRollupLevel
                        GROUP  BY ID) B 
                    ON A.ID = B.ID 
                       --AND B.numPlacements <> A.numPlacements 
 WHERE  A.numPlacements <> B.numPlacements or A.numPlacements is null or B.numPlacements is null

关于为什么的任何想法?

以下基于ypercube建议的详细信息:

我创建了TableA和TableB。它们看起来像这样:

TableA
ID  numPlacements
1   10
2   20
3   30
4   40

TableB
ID  numPlacements
2   20
3   31
4   40
5   50

请注意,差异是TableA没有#5,TableB没有#1,而#3在两者中都有不同的numPlacements。

SELECT CASE WHEN A.ID is NULL THEN B.ID ELSE A.ID END AS 'ID',
       A.numPlacements AS 'AnumPlacements', 
       B.numPlacements  AS 'BnumPlacements',
       B.numPlacements - A.numPlacements as 'Variance'
FROM   (SELECT ID,
               Sum(numPlacements) AS 'numPlacements' 
        FROM   TableA
        GROUP  BY ID) A 
       FULL OUTER JOIN (SELECT ID,
                               Sum(numPlacements) AS 'numPlacements' 
                        FROM   TableB
                        GROUP  BY ID) B 
                    ON A.ID = B.ID 

以上完全符合我的期望:

ID  AnumPlacements  BnumPlacements  Variance
1   10              NULL            NULL
2   20              20              0
3   30              31              1
4   40              40              0
5   NULL            50              NULL

让我们尝试添加WHERE子句。

SELECT CASE WHEN A.ID is NULL THEN B.ID ELSE A.ID END AS 'ID',
       A.numPlacements AS 'AnumPlacements', 
       B.numPlacements  AS 'BnumPlacements',
       B.numPlacements - A.numPlacements as 'Variance'
FROM   (SELECT ID,
               Sum(numPlacements) AS 'numPlacements' 
        FROM   TableA
        GROUP  BY ID) A 
       FULL OUTER JOIN (SELECT ID,
                               Sum(numPlacements) AS 'numPlacements' 
                        FROM   TableB
                        GROUP  BY ID) B 
                    ON A.ID = B.ID 
 WHERE  A.numPlacements <> B.numPlacements or A.numPlacements is null or B.numPlacements is null

使用where,我们得到三个预期的行:

ID  AnumPlacements  BnumPlacements  Variance
1   10              NULL            NULL
3   30              31              1
5   NULL            50              NULL

让我们尝试添加AND。

SELECT CASE WHEN A.ID is NULL THEN B.ID ELSE A.ID END AS 'ID',
       A.numPlacements AS 'AnumPlacements', 
       B.numPlacements  AS 'BnumPlacements',
       B.numPlacements - A.numPlacements as 'Variance'
FROM   (SELECT ID,
               Sum(numPlacements) AS 'numPlacements' 
        FROM   TableA
        GROUP  BY ID) A 
       FULL OUTER JOIN (SELECT ID,
                               Sum(numPlacements) AS 'numPlacements' 
                        FROM   TableB
                        GROUP  BY ID) B 
                    ON A.ID = B.ID 
                       AND B.numPlacements <> A.numPlacements 

现在,如果我们在连接中使用上面的AND尝试它,我希望得到第3行。 相反,我得到了这个:

ID  AnumPlacements  BnumPlacements  Variance
1   10              NULL            NULL
2   NULL            20              NULL
2   20              NULL            NULL
3   30              31              1
4   NULL            40              NULL
4   40              NULL            NULL
5   NULL            50              NULL

0 个答案:

没有答案