ОСНОВНИЙ оператор проти НЕ В


Відповіді:


29

Існує дві ключові відмінності між EXCEPTта NOT IN.

ПРИКЛАДНО

EXCEPTфільтрує DISTINCTзначення з лівої таблиці, які не відображаються в правій таблиці. Це по суті те саме, що робити NOT EXISTSз DISTINCTпунктом.

Також очікується, що дві таблиці (або підмножина стовпців із таблиць) матимуть однакову кількість стовпців у лівій та правій частині запиту

Наприклад, ви не можете:

SELECT ID, Name FROM TableA
EXCEPT
SELECT ID FROM TableB

Це призведе до помилки:

Усі запити, об’єднані за допомогою оператора UNION, INTERSECT або EXCEPT, повинні мати рівну кількість виразів у своїх цільових списках.

НЕ В

NOT INне фільтрує DISTINCTзначення та не повертає всіх значень з лівої таблиці, які не відображаються в правій таблиці.

NOT IN вимагає порівняння одного стовпця з однієї таблиці з одним стовпцем з іншої таблиці або підзапиту.

Наприклад, якщо ваш підзапит повинен повернути кілька стовпців:

SELECT * FROM TableA AS nc
WHERE ID NOT IN (SELECT ID, Name FROM TableB AS ec)

Ви отримаєте таку помилку:

У списку вибору може бути вказаний лише один вираз, коли підзапит не вводиться з EXISTS.

Однак, якщо в правій таблиці міститься NULLзначення у значеннях, які фільтруються NOT IN, повертається порожній набір результатів, що потенційно дає несподівані результати.

ПРИКЛАД

CREATE TABLE #NewCustomers (ID INT);
CREATE TABLE #ExistingCustomers (ID INT);

INSERT INTO #NewCustomers
        ( ID )
VALUES
     (8), (9), (10), (1), (3), (8);

INSERT INTO #ExistingCustomers
        ( ID )
VALUES
        ( 1) , (2), (3), (4), (5);


-- EXCEPT filters for DISTINCT values
SELECT * FROM #NewCustomers AS nc
EXCEPT
SELECT * FROM #ExistingCustomers AS ec

-- NOT IN returns all values without filtering
SELECT * FROM #NewCustomers AS nc
WHERE ID NOT IN (SELECT ID FROM #ExistingCustomers AS ec)

З вищезазначених двох запитів EXCEPTповертає 3 рядки з #NewCustomers, фільтруючи 1 і 3, які відповідають, #ExistingCustomersі дублікат 8.

NOT INне робить це чітке фільтрування і повертає 4 рядки #NewCustomersз дубліката 8.

Якщо ми тепер додамо в NULLдо #ExistingCustomersтаблиці, ми бачимо одні і ті ж результати , що повертаються EXCEPT, проте NOT INповертає порожній результуючий набір.

INSERT INTO #ExistingCustomers
        ( ID )
VALUES
        ( NULL );

-- With NULL values in the right-hand table, EXCEPT still returns the same results as above
SELECT * FROM #NewCustomers AS nc
EXCEPT
SELECT * FROM #ExistingCustomers AS ec

-- NOT IN now returns no results
SELECT * FROM #NewCustomers AS nc
WHERE ID NOT IN (SELECT ID FROM #ExistingCustomers AS ec)

DROP TABLE #NewCustomers;
DROP TABLE #ExistingCustomers;

Замість цього NOT INвам слід по-справжньому подивитися, NOT EXISTSі в блозі Гейл Шоу є хороше порівняння між ними .


Чи використовуватиме EXCEPT індекси, якщо це доречно?
JohnOpincar

1

Доповнення до відмінного коментаря Марка Сінкінсона:

NOT IN вимагає порівняння одного стовпця з однієї таблиці з одним стовпцем з іншої таблиці або підзапиту.

Насправді ви можете виконати NOT INбільше, ніж один стовпець.
Наприклад, це законно * запит SQL:

SELECT  E.first_name, E.last_name
FROM    employees E
WHERE   (E.first_name, E.last_name) NOT IN 
              (SELECT M.first_name, M.last_name FROM managers M)

Що повернеться first_nameі last_nameвсіх людей, які є працівниками, але не є також менеджерами.

*: але конструкція ще не реалізована в SQL Server.


-2

Звернення NOT IN не вдається, оскільки має бути співвідношення предикатів у головному запиті та підзапиті. Якщо ви не залишите його, ви отримаєте непідписаний підзапит.

ВИБІР * З ТАБЛИЦІ AS AS nc, де ідентифікується НЕ (SELECT ID, ім'я від TableB як ec, де nc.ID = ec.ID)

EXCEPT краще і буде обробляти будь-які нульові рядки без використання предикатів IS NULL / IS NOT NULL.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.