Difference between IS NULL criteria in JOIN and WH

2019-02-19 06:03发布

问题:

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) 

I ran the below queries, and I get 2 different outputs.

Second is the desired output.

I cannot understand the reason for output given by query1.

Please assist me to understand the result.

-- 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:

In query 1 we have b.id is null in join criteria, which because being LEFT JOIN on A returns all rows of A irrespective of JOIN criteria and therefore returns 3 rows for table A.

In query 2 first LEFT JOIN on A returns 3 rows and then where b.id is null is applied on these 3 rows which leaves the third row and results in only 1 rows for the third row for id=3 .

Further explanation:

Your comment

Though in Query1 how come b.id is null ??

requires detailed explanation

as I said in Query 1 for each row of A there is a row returned in Left join irrespective of criteria of JOIN

so your join criteria is actually

a.id = b.id and b.id is null

a logical And between two criteria which cannot be true simultaneously as if b.id is null is true then a.id=null is being matched which is basically null

output is given here in this fiddle: http://sqlfiddle.com/#!3/c20ba/1

and is like

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

Another point to note: Do note that in SQL id=NULL is evaluated as NULL. Also note that when doing logical operations like AND OR in sql query, NULL behaves quite peculiarly. See the msdn documentation on this behavior

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


回答2:

This one is not correct:

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

you want b.id to be null AND, at the same time, to be b.id = a.id. This can never be true, so the join will not succeed. You will get all rows from #t1 table but all null values for #t2.

This one is correct:

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

you are using a LEFT JOIN, so your query will return all rows from #t1 and only the rows from #t2 where the join succeeds (and it will succeed when a.id = b.id).

When the join doesn't succeed, b.id will be set to null. Using WHERE b.id is null you will get only the rows where the join won't succeed and you will get all values from #t1 which are not present in #t2.

You can try to run this query to see what's actually happening and to better understand the logic:

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