Ако b
е nullable, това не е грешка. Проблемът е, че SQL Server превръща NOT IN
в поредица от <> 1 AND <> 2 AND <> 3
и т.н. Ако имате <> NULL
, което връща неизвестно, което в този случай означава невярно. В различни сценарии това може да квалифицира или дисквалифицира ВСИЧКИ редове. Вместо LEFT JOIN
подход, трябва да кажете:
FROM dbo.OuterTable AS t
WHERE NOT EXISTS (SELECT 1 FROM x WHERE b = t.a);
Ето бърза демонстрация:
DECLARE @x TABLE(i INT);
INSERT @x VALUES(1),(2);
DECLARE @y TABLE(j INT);
INSERT @y VALUES(2),(NULL);
SELECT i FROM @x WHERE i NOT IN -- produces zero results
(SELECT j FROM @y);
SELECT i FROM @x AS x WHERE NOT EXISTS -- produces one result
(SELECT 1 FROM @y WHERE j = x.i);
За много повече подробности (и показатели, за да докажете защо NOT EXISTS
е най-добрата алтернатива):
http://www.sqlperformance.com /2012/12/t-sql-queries/left-anti-semi-join
Също така, моля, прочетете тази публикация в блога от Гейл Шоу:
http://sqlinthewild. co.za/index.php/2010/02/18/not-exists-vs-not-in/