Почему оператор <> завершается неудачно и возвращает все записи? - PullRequest
0 голосов
/ 02 июля 2018

В течение последнего часа я выдергивал свои волосы по этому запросу, и его результат

select ac.* from [finance].[Accounts] ac
    inner join finance.AccountMapping ap
    on ap.Account_ID <> ac.AccountID

в таблице счетов у нас есть идентификаторы счетов 1,2,3,4,5,6 и в таблице AccountMapping у нас есть account_ID 1,2

но вышеупомянутый запрос все еще возвращает записи для 1,2. Зачем? Я упомянул возврат записей, которые не совпадают.

Ответы [ 4 ]

0 голосов
/ 02 июля 2018

Попробуйте с левым соединением, и Account_ID второй таблицы имеет нулевое условие:

SELECT ac.* from [finance].[Accounts] ac
LEFT JOIN finance.AccountMapping ap
ON ap.Account_ID= ac.AccountID'
WHERE ap.Account_ID IS NULL

Надеюсь, это поможет вам.

0 голосов
/ 02 июля 2018

Вы ищете результат, достижимый с ИСКЛЮЧЕНИЕМ:

Select AccountID from AccountMapping
Except
Select AccountID from Accounts 
0 голосов
/ 02 июля 2018

Вы неправильно понимаете, как работает предложение ON внутреннего соединения: для каждой записи первой таблицы будет найдено всех записей в объединенной таблице, которые удовлетворяют условию. Пока вы выполняете эквиджоин на внешнем первичном ключе, вы получаете не более одной записи. Как только вы переключитесь на <>, >, < и т. Д., Вы можете получить несколько объединенных записей для каждой записи первой таблицы.

В вашем примере вы ищете все строки, где ID не совпадает. Это идеальный случай для экзистенциального квантификатора, т.е. оператор EXISTS:

SELECT *
FROM [finance].[Accounts] ac
WHERE NOT EXISTS (
    SELECT *
    FROM finance.AccountMapping ap
    WHERE ap.Account_ID = ac.AccountID
)
0 голосов
/ 02 июля 2018

Поскольку каждая запись в ac предположительно имеет хотя бы одну запись в ap, где значения не совпадают. Вы, вероятно, намереваетесь:

select ac.*
from finance.Accounts ac left join
     finance.AccountMapping ap
      on ap.Account_ID = ac.AccountID
where ap.Account_ID is null;

Или это может быть немного более прямым:

select ac.*
from finance.Accounts ac
where not exists (select 1
                  from finance.AccountMapping ap
                  where ap.Account_ID = ac.AccountID
                 );
...