简体   繁体   中英

Filter from same table in Oracle

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.

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).

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.

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;

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