Reputation: 1557
When I run my query as INNER JOIN
between two tables, I get the correct result - 182 in all.
However, when I run the query as LEFT JOIN
, I get only 8 records back. Am I performing the join incorrectly?
First the code:
select e.username,
e.password,
coalesce(r.access_level, 0) as orgid
from employees e
left join retired r
on e.employeeid = r.employeeid
where access_level=3
The Retired
table has only 182 records. Both tables are related by EmployeeId
.
The 82 records in Retired
table also exist in Employees
but Employees
table has over 7 thousand records.
One of the fieldnames Retired
is called Access_Level
with a value of 3.
Any ideas why LEFT JOIN
isn't giving me an accurate result?
Upvotes: 0
Views: 2838
Reputation: 424983
The trick with outer joins and conditions is to move the condition from the where clause into the join condtions clause:
select
e.username,
e.password,
coalesce(r.access_level, 0) as orgid
from employees e
left join retired r
on e.employeeid = r.employeeid
and access_level=3
The reason you must do this is that the where clause is a filter on the rowset,which executes after the joins are made. By having a condition on the outer joined table in the where clause you effectively make the outer join into an inner join, because missed outer joins have null
values in the columns of the joined table, but a condition in the where clause will insist there is a value there.
Conditions in the join clause are executed as the join is made, so by moving the condition out of the where clause, you allow the join to miss while still imposing the condition, but return an all-null joined row if no suitable row is found in the joined table.
After some more info from comments, it seems this is what you wanted:
select distinct
e.username,
e.password,
coalesce(r.access_level, 0) as orgid
from employees e
join retired r
on e.employeeid = r.employeeid
and access_level=3
Upvotes: 2
Reputation: 38345
If Access_Level
is a column in the Retired
table then its value will be NULL
for any rows in Employee that don't have a corresponding row in Retired. Those rows will then be filtered out by your WHERE clause as they don't have a Access_Level
of 3. Moving that condition to the ON
clause should be enough:
select e.username,
e.password,
coalesce(r.access_level, 0) as orgid
from employees e
left join retired r
on e.employeeid = r.employeeid and access_level=3
Upvotes: 3
Reputation: 7219
Using a field from the retired table in your WHERE clause is basically automatically performing an INNER JOIN, because only records that have a valid access_level value (i.e., NOT NULL) are being returned.
If you want to see all records from employee, you would need to modify your WHERE clause to account for employee records that do not have a match in retired, such as saying WHERE r.access_level = 3 OR r.employeeid IS NULL
.
Upvotes: 2