2013-08-04 4 views
1

Я читал статью, в которой объяснялась разница между предложением join и in и exists, но я смутился объяснением разных результатов при использовании предложения NOT IN vs. NOT EXISTS. Может ли кто-нибудь уточнить, почему существует разница между выводом для предложения NOT EXISTS против предложения NOT IN? Я попытался удалить строку NULL (t2.id = 8) из таблицы t2 и получил тот же результат.JOIN vs. IN vs. EXISTS

Вот SQL скрипт из этой статьи:

CREATE TABLE t1 (id INT, title VARCHAR(20), someIntCol INT) 
GO 
CREATE TABLE t2 (id INT, t1Id INT, someData VARCHAR(20)) 
GO 

INSERT INTO t1 
SELECT 1, 'title 1', 5 UNION ALL 
SELECT 2, 'title 2', 5 UNION ALL 
SELECT 3, 'title 3', 5 UNION ALL 
SELECT 4, 'title 4', 5 UNION ALL 
SELECT null, 'title 5', 5 UNION ALL 
SELECT null, 'title 6', 5 

INSERT INTO t2 
SELECT 1, 1, 'data 1' UNION ALL 
SELECT 2, 1, 'data 2' UNION ALL 
SELECT 3, 2, 'data 3' UNION ALL 
SELECT 4, 3, 'data 4' UNION ALL 
SELECT 5, 3, 'data 5' UNION ALL 
SELECT 6, 3, 'data 6' UNION ALL 
SELECT 7, 4, 'data 7' UNION ALL 
SELECT 8, null, 'data 8' UNION ALL 
SELECT 9, 6, 'data 9' UNION ALL 
SELECT 10, 6, 'data 10' UNION ALL 
SELECT 11, 8, 'data 11' 

А вот запросы SQL и их объяснение:

- IN не получить правильные результаты. - Это связано с тем, как IN обрабатывает NULL и трехзначную логику. - NULL рассматривается как неизвестный, поэтому, если в t2.t1id есть нуль - NOT IN будет возвращать либо НЕ ИСТИННО, либо НЕ НЕИЗВЕСТНО. И ни один из них не может быть ИСТИННЫМ. - когда в столбце t1id таблицы t2 есть NULL, запрос NOT IN всегда возвращает пустой набор.

SELECT t1.* 
FROM t1 
WHERE t1.id NOT IN (SELECT t1id FROM t2) 

- НЕ СУЩЕСТВУЕТ получает правильные результаты

SELECT t1.* 
FROM t1 
WHERE NOT EXISTS (SELECT * FROM t2 WHERE t1.id = t2.t1id) 
GO 

DROP TABLE t2 
DROP TABLE t1 

Вот ссылка на статью: http://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210.aspx

Спасибо!

+0

Вот лучшая статья: http://www.sqlperformance.com/2012/12/t-sql-queries/left-anti-semi-join Кроме того, в чем ваш вопрос? –

+0

@TimSchmelter «Может кто-нибудь уточнить, почему существует разница между выводом для предложения NOT EXISTS против предложения NOT IN?» – Jocke

+0

@Jocke: Но он добавил объяснение позже сам, это сбивает с толку. –

ответ

0

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

Возможно, вы можете получить тот же результат, используя как NOT IN, так и NOT EXISTS, но вы можете увидеть различия в запросе, которые включают значение NULL. Потому что NOT EXISTS - единственный способ получить эти строки с значением NULL.

Вы можете увидеть его лучше в этом примере:

update cars set c_owner = NULL where c_id = BMW03444 

Ну ... Давайте попробуем увидеть, если у нас есть какой-либо автомобиль на складе, который не был продан еще.

select count(*) from cars where c_owner not it (select c_name from customers); 

Выход:

COUNT (*): 0

Где провал? Довольно просто. Вы не запрашиваете группу автомобилей, чьи покупатели не были включены в список. Вы просто просите машину без хозяина. Никто, даже если его нет в списке. Правильная форма:

select count(*) 
from cars c1 
where not exists (
    select c_owner 
    from customers c2 
    where c1.c_owner=c2.customer_id 
); 

COUNT (*): 1

Это потому, что NOT IN потребности конкретных значений для проверки в Так NULL значения устанавливаются как FALSE и не рассчитывала.. NOT EXISTS проверяет отсутствие элемента в наборе, поэтому значения NULL установлены как ИСТИНА и включены.

Смежные вопросы