SQL Server: полное внешнее соединение, включено или где

Я искал это и не могу найти ответ. Я заранее извиняюсь, так как уверен, что этот ответ уже есть, но я не могу его найти.

Я работаю с БД SQL Server 2005 и знаю, что приведенный ниже запрос не представляет нормализованную БД, поскольку поле numPlacements находится как в таблице сведений, так и в сводной таблице. Я не создал БД.

Приведенный ниже SQL дает ожидаемый результат при использовании предложения where. Ожидаемый результат - все строки, в которых совпадающее значение отсутствует в любой из таблиц или два значения не совпадают.

Однако, если я прокомментирую предложение where и раскомментирую окончательное AND в предложении ON, он вернет более 200 тыс. Строк вместо ожидаемых 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

С помощью где мы получаем три ожидаемых строки:

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 ответов

Другие вопросы по тегам