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 EXISTSNOT EXISTSсрещуNOT IN