SQL Not Exists включает нулевое значение

У меня есть две таблицы SQL Server:

Таблица 1

Id name   description     version
----------------------------------
1  Book1  Book 1 Title    v1
2  Book2  Book 2 Title    v2
3  Book3  Book 3 Title    NULL
4  Book5  Book 5 Title    v3

Таблица 2

Id name   description     version
----------------------------------
1  Book1  Book 1 Title    v1
2  Book2  Book 2 Title    v2
3  Book3  Book 3 Title    NULL
4  Book4  Book 4 Title    NULL
5  Book5  Book 5 Title    NULL

Я хочу выбрать все данные из таблицы 2, которых нет в таблице 1, чтобы я мог вставить их в другую таблицу.

Вот SQL-запрос:

SELECT t2.name, t2.description, t2.version
FROM Table2 AS t2
WHERE  
    NOT EXISTS (SELECT t1.name, t1.description, t1.version 
                FROM Table1 as t1 
                WHERE t2.name = t1.name 
                  AND t2.description = t1.description  
                  AND t2.version = t1.version)

Ожидаемый результат таков:

Id name   description     version
-----------------------------------
4  Book4  Book 4 Title    NULL
5  Book5  Book 5 Title    NULL

Но вместо этого я получаю это:

Id name   description     version
---------------------------------
3  Book3  Book 3 Title    NULL
4  Book4  Book 4 Title    NULL

Почему нулевое значение не оценивается в моем выражении NOT EXIST и отображается?


person lory    schedule 27.08.2018    source источник
comment
Значение NULL при сравнении с чем-либо вернет FALSE. Вам нужно будет использовать INSULL() для обработки   -  person Squirrel    schedule 27.08.2018
comment
потому что NULL = NULL ложно. Иметь первичный ключ проще. Также проверьте ОБНОВЛЕНИЕ.   -  person qxg    schedule 27.08.2018
comment
Взгляните на функцию MERGE в SQL Server — docs.microsoft.com/en-us/sql/t-sql/statements/   -  person WynDiesel    schedule 27.08.2018


Ответы (4)


Оптимизированный запрос:

SELECT t2.name, t2.description, t2.version 
FROM Table2 AS t2
LEFT JOIN Table1 AS t1 
ON t2.name = t1.name 
 AND t2.description = t1.description  
 AND (t2.version     = t1.version
     OR  (t2.version IS NULL AND t1.version IS NULL))
WHERE t1.ID is NULL
person Prahalad Gaggar    schedule 27.08.2018
comment
Лучше использовать NVL вот так NVL(t2.version, '-') = NVL(t1.version, '-') - person Sahil Gulati; 30.04.2021

Значение NULL при сравнении с чем-либо вернет FALSE. Вам нужно будет использовать IS NULL для обработки

select t2.name, t2.description, t2.version
from   Table2 as t2
WHERE  NOT EXISTS 
       ( 
            SELECT *
            FROM   Table1 as t1 
            WHERE  t2.name        = t1.name 
            AND    t2.description = t1.description 
            AND    (
                       t2.version     = t1.version
                   OR  (t2.version IS NULL AND t1.version IS NULL)
                   )
       )
person Squirrel    schedule 27.08.2018
comment
Это не сработает, если у меня есть нулевая версия в таблице 2, а не в таблице 1. Смотрите мой обновленный пост - person lory; 27.08.2018
comment
Разве этот запрос не дает ожидаемого результата? - person Squirrel; 27.08.2018
comment
это не так, поскольку идентификатор 5 в таблице 2 отсутствует, потому что версия равна нулю - person lory; 27.08.2018
comment
я пробовал, и это дало тот же ожидаемый результат, который вы опубликовали - person Squirrel; 28.08.2018
comment
мм странно. Позвольте мне снова проверить. Мой кофе был не таким крепким, когда я тестировал, я думаю, лол. - person lory; 28.08.2018

вы можете использовать EXCEPT для этой проблемы. вы можете использовать общее поле из двух таблиц, а затем выбрать данные из этого результата.

посмотрите этот следующий код:

SELECT name, description, version FROM Table2
EXCEPT
SELECT name, description, version FROM Table1

этот код дает вам данные, которые существуют в таблице 2, но не существуют в таблице 1.

person Masoud Amidi    schedule 27.08.2018
comment
Мне нужно сравнить имя, название и версию, а не идентификаторы. - person lory; 27.08.2018
comment
вам просто нужно назвать свои столбцы. и его работы. он также учитывает нулевые значения. сначала проверьте этот код. а потом ответь. Спасибо - person Masoud Amidi; 27.08.2018
comment
Проблема с EXCEPT заключается в том, что я не могу выбрать больше столбцов, чем указано в моем запросе EXCEPT, но NOT EXIST или LEFT JOIN делает - person lory; 27.08.2018
comment
Я думаю, вы не знаете, чего хотите, и с моим решением вы все это покрываете. - person Masoud Amidi; 27.08.2018
comment
Luv знал, чего я хотел, и решил мою проблему. Хорошего дня - person lory; 27.08.2018

Вы можете использовать просто функцию ISNULL():

SELECT t2.name, t2.description, t2.version
FROM Table2 AS t2
WHERE  
    NOT EXISTS (SELECT t1.name, t1.description, t1.version 
                FROM Table1 as t1 
                WHERE t2.name = t1.name 
                  AND t2.description = t1.description  
                  AND ISNULL(t2.version,0) = ISNULL(t1.version,0)
person Elena Pilipus    schedule 14.10.2020