SELECT foreignStockId
FROM [Subset].[dbo].[Products]
Вероятно връща NULL
.
A NOT IN
заявката няма да върне никакви редове, ако има NULL
s съществува в списъка с NOT IN
стойности. Можете изрично да ги изключите, като използвате 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
според таблиците на истинността за три стойностна логика.
Следните връзки съдържат допълнителна дискусия относно производителността на различните опции.
- Трябва ли да използвам
NOT IN
,OUTER APPLY
,LEFT OUTER JOIN
,EXCEPT
, илиNOT EXISTS
? NOT IN
срещуNOT EXISTS
срещуLEFT JOIN / IS NULL
:SQL ServerLeft outer join
срещуNOT EXISTS
NOT EXISTS
срещуNOT IN