Reputation: 69
I have a table and I want to filter result from same table. Here is a sample.
STUDENT_ID | SCHOOL_YEAR |
-----------+-------------+
747 | 20122013 |
747 | 20132014 |
748 | 20122013 |
749 | 20122013 |
749 | 20132014 |
750 | 20122013 |
751 | 20112012 |
I want to sort the table so that only those student_id show up who has 20122013 school year but NOT 20132014.
So the result would be
STUDENT_ID |
-----------+
748 |
750 |
I tried to UNION and LEFT/RIGHT JOIN but no luck.
Please help. Thanks.
Upvotes: 0
Views: 57
Reputation: 52376
For very large data sets you'd probably want to avoid the implicit and unnecessary distinct on a minus, and use a NOT IN or NOT EXISTS:
select student_id
from tbl
where school_year = '20122013' and
student_id not in (
select student_id
from tbl
where school_year = '20132014');
or
select student_id
from tbl t1
where school_year = '20122013' and
not exists (
select null
from tbl t2
where school_year = '20132014' and
t2.student_id = t1.student_id);
The latter would be especially handy if their were potentially multiple rows per student_id in the subquery set.
Upvotes: 1
Reputation: 5820
Minus is the easy way:
select student_id
from tbl
where school_year = '20122013'
minus
select student_id
from tbl
where school_year = '20132014';
STUDENT_ID
----------
748
750
You could also do this with an "anti-join":
select a.student_id
from tbl a
left outer join tbl b
on a.student_id = b.student_id
and b.school_year = '20132014'
where
a.school_year = '20122013'
and b.student_id is null;
STUDENT_ID
----------
750
748
With the anti-join, you are outer joining the second copy of the table ("b" in this example) and then filtering where the rows from that set did not match (b.student_id is null).
Upvotes: 3
Reputation: 954
Personally, I prefer the minus
answer, but an outer join can be used as well.
SELECT t1.student_id
FROM tbl t1
LEFT JOIN tbl t2
ON (t2.student_id = t1.student_id AND t2.school_year = '20132014')
WHERE school_year = '20122013'
AND t2.student_id IS NULL;
Upvotes: 0