Разница между критериями IS NULL в JOIN и WHERE в запросе

create table #t1 (id int) create table #t2 (id int) insert into #t1 values (1) insert into #t1 values (2) insert into #t1 values (3) insert into #t2 values (1) insert into #t2 values (2) 

Я выполнил следующие запросы, и у меня есть два разных выхода.

Второй – желаемый выход.

Я не могу понять причину вывода, заданного query1.

Пожалуйста, помогите мне понять результат.

 -- Query1 select * from #t1 a left join #t2 b on a.id = b.id and b.id is null -- Query2 select * from #t1 a left join #t2 b on a.id = b.id where b.id is null 

В запросе 1 мы имеем b.id is null , b.id is null в критериях соединения, потому что, поскольку LEFT JOIN на A возвращает все строки A независимо от критериев JOIN и поэтому возвращает 3 строки для таблицы A.

В запросе 2 сначала LEFT JOIN на A возвращает 3 строки, а затем, where b.id is null , применяется к этим 3 строкам, которые выходят из третьей строки и приводят к 1 строке для третьей строки для id = 3.

Дальнейшее объяснение:

Ваш комментарий

Хотя в Query1, как b.id имеет значение null?

требует подробного объяснения

как я сказал в Query 1 для каждой строки A, есть строка, возвращаемая в Left join, независимо от критериев JOIN

поэтому ваши критерии присоединения на самом деле

a.id = b.id и b.id – null

логическое И между двумя критериями, которые не могут быть истинными одновременно, как если бы b.id было null, является истинным, тогда выполняется сопоставление a.id = null, которое в основном равно нулю

вывод приводится здесь в этой скрипке: http://sqlfiddle.com/#!3/c20ba/1

и как

 id | id ________ 1 | null 2 | null 3 | null 

Еще одно замечание: обратите внимание, что в SQL id=NULL оценивается как NULL . Также обратите внимание, что при выполнении логических операций, таких как AND OR в sql-запросе, NULL ведет себя довольно необычно. См. Документацию msdn по этому поведению

 null and true = null null and false=false null and null =null null or null =null null or true= true null or false=null 

Это неверно:

 select * from #t1 a left join #t2 b on a.id = b.id and b.id is null 

вы хотите, чтобы b.id был нулевым и, в то же время, b.id = a.id Это никогда не может быть правдой, поэтому соединение не будет выполнено. Вы получите все строки из таблицы # t1, но все значения NULL для # t2.

Это верно:

 select * from #t1 a left join #t2 b on a.id = b.id where b.id is null 

вы используете LEFT JOIN, поэтому ваш запрос вернет все строки из # t1 и только строки из # t2, где соединение будет успешным (и оно будет успешным, если a.id = b.id ).

Когда соединение не будет выполнено, b.id будет установлено значение null. Использование WHERE b.id is null вы получите только строки, в которых соединение не будет выполнено, и вы получите все значения из # t1, которых нет в # t2.

Вы можете попробовать запустить этот запрос, чтобы узнать, что на самом деле происходит, и лучше понять логику:

 select * from #t1 a left join #t2 b on a.id = b.id 
  • Запрос двух соединений на одно и то же значение и таблицу
  • Как объединить два запроса результатов запроса в один результат с помощью sp?
  • Дублировать строку, вставленную в отдельную таблицу, в то время как вставка с использованием нескольких таблиц слева
  • SQL Server: результаты с левым соединением уменьшают количество строк, чем в левой таблице
  • Заменить Left Outer Присоединиться к нулевым значениям со строкой
  • Left Outer Join Не сохраняет левую таблицу
  • SQL Server ROW_NUMBER Влево Присоединиться +, если вы не знаете имена столбцов
  • Запрошенная SQL-запрос: таблица SELECT A с таблицей B (максимальная или нулевая)
  • Почему левое соединение переходит во внутреннее соединение, если внутреннее соединение включено в запрос?
  • SQL Server - Присоединиться к вопросу - 3 таблицы
  • Возьмите одну строку со стола
  • Давайте будем гением компьютера.