Ответ 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
за таблицы истинности для трехзначной логики.
В следующих ссылках содержится дополнительная информация о производительности различных параметров.