简体   繁体   中英

Wrong behaviour with left outer join?

SQL Fiddle : http://sqlfiddle.com/#!2/49db7/2

create table EmpDetails
(
emp_code int,
e_type     varchar(10)
);

insert into EmpDetails values (100,'A');
insert into EmpDetails values (101,'D');
insert into EmpDetails values (102,'A');
insert into EmpDetails values (103,'D');

create table QDetails
(
id  int,
emp_code int,
dn_num int
);

insert into QDetails values (1,100,NULL);
insert into QDetails values (2,101,4343);
insert into QDetails values (3,101,4343);
insert into QDetails values (4,103,NULL);
insert into QDetails values (5,103,NULL);
insert into QDetails values (6,100,NULL);

select * from EmpDetails
select * from QDetails

-- expected result

1   100 NULL
6   100 NULL
2   101 4343
3   101 4343

--When e_type = A it should include rows from QDetails doesn't matter dn_num is null or not null --but when e_type = D then from QDetails it should include only NOT NULL values should ignore null

select e.emp_code, e.e_type, q.dn_num from empdetails e left join qdetails q
on e.emp_code = q.emp_code and (e.e_type = 'D' and q.dn_num is not null)

--Above query I tried includes 103 D NULL which I don't need and exclueds 6 100 NULL which i need.

Your problem is your q.dn_num is not null condition, it is specifically excluding those records that you state that you want. Removing that should fix it.

select e.emp_code, e.e_type, q.dn_num 
from empdetails e 
left join qdetails q
   on e.emp_code = q.emp_code 
WHERE (e.e_type = 'D' and q.db_num is not null)
OR e.e_type = 'A'

Additionally, it is a general convention to use your join to specify only the join criteria and your where clause to filter (there are reasons why you may not want to do this, but depends on your query).

Writing your queries as above may make them easier to read later on.

I am not sure why you are using left join here.
You can get the results you specified with inner join

select
  e.emp_code
  ,e.e_type
  ,q.dn_num 
from 
  empdetails e 
  inner join qdetails q on e.emp_code = q.emp_code
where 
  e.e_type = 'A'
  or (e.e_type = 'D' and q.dn_num is not null)
order by
  e.emp_code
  ,e.e_type

The left join would be used if you also wanted to list records from empdetails table that have no match in qdetails

SELECT     e.emp_code, 
           e.e_type,  
           q.dn_num 
FROM       empdetails e 
           LEFT JOIN  qdetails q
               ON e.emp_code = q.emp_code 
WHERE      (
               e.e_type = 'A' OR 
              (
                 e.e_type = 'D' AND
                  q.dn_num is not null
              )
           ) AND q.id is not null 

SQL Fiddle Demo

You need to implement the logic correctly. Your conditions mention 'A' , but that is not in the conditions.

Then, you don't need a left join . You don't want emp_code = 102 . This has no matches, so presumably it drops out.

The following seems to implement the logic:

select e.emp_code, e.e_type, q.dn_num , q.id
from empdetails e join
     qdetails q
     on e.emp_code = q.emp_code
where (e.e_type = 'D' and q.dn_num is not null) or
      e.e_type = 'A';

This is the correct query.

        select q.id,e.emp_code,q.dn_num 
        from empdetails e join qdetails q
        on e.emp_code = q.emp_code
        where (e.e_type = 'D' and q.dn_num is not null)  or  e.e_type = 'A'  order by e.e_type;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM