Подтвердить что ты не робот

SQL NOT IN не работает

У меня есть две базы данных, одна из которых содержит инвентарь, а другая - подмножество записей первичной базы данных.

Следующий оператор SQL не работает:

SELECT  stock.IdStock
        ,stock.Descr       
FROM    [Inventory].[dbo].[Stock] stock
WHERE   stock.IdStock NOT IN
        (SELECT foreignStockId FROM
         [Subset].[dbo].[Products])

Не в не работает. Удаление NOT дает правильные результаты, то есть продукты, которые находятся в обеих базах данных. Однако использование NOT IN не возвращает никаких результатов.

Что я делаю неправильно, любые идеи?

4b9b3361

Ответ 1

SELECT foreignStockId
FROM   [Subset].[dbo].[Products]  

Вероятно, возвращает a NULL.

A NOT IN запрос не будет возвращать строки, если в списке значений NOT IN существует любой NULL. Вы можете явно исключить их с помощью IS NOT NULL, как показано ниже.

SELECT stock.IdStock,
       stock.Descr
FROM   [Inventory].[dbo].[Stock] stock
WHERE  stock.IdStock NOT IN (SELECT foreignStockId
                             FROM   [Subset].[dbo].[Products]
                             WHERE  foreignStockId IS NOT NULL) 

Или перепишите с помощью NOT EXISTS.

SELECT stock.idstock,
       stock.descr
FROM   [Inventory].[dbo].[Stock] stock
WHERE  NOT EXISTS (SELECT *
                   FROM   [Subset].[dbo].[Products] p
                   WHERE  p.foreignstockid = stock.idstock) 

Помимо наличия семантики, которую вы хотите, план выполнения для NOT EXISTS часто проще как показано здесь.

Причина разницы в поведении сводится к трехзначной логике, используемой в SQL. Предикаты могут оцениваться до True, False или Unknown.

Предложение

A WHERE должно оцениваться до True, чтобы строка возвращалась, но это невозможно при использовании NOT IN, когда NULL присутствует, как описано ниже.

'A' NOT IN ('X','Y',NULL) эквивалентно 'A' <> 'X' AND 'A' <> 'Y' AND 'A' <> NULL)

  • 'A' < > 'X' = True
  • 'A' < > 'Y' = True
  • 'A' < > NULL = Unknown

True AND True AND Unknown оценивает Unknown за таблицы истинности для трехзначной логики.

В следующих ссылках содержится дополнительная информация о производительности различных параметров.

Ответ 2

Если НЕ IN не работает, вы всегда можете попытаться сделать LEFT JOIN. Затем фильтруйте WHERE, используя одно из значений из объединенной таблицы, которые NULL. При условии, что значение, с которым вы соединялись, не содержит значения NULL.