Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performing set subtraction on a single table

Tags:

sql

mysql

I have a table that stores membership records. One record per member, per year. eg:

MEMBER   YEAR
--------------
steve    2011
steve    2010
bob      2010
jane     2011

What I'm trying to generate is a list of lapsed members (those who haven't renewed) for a given year. Something like "get all members who have an entry for 2010 but not 2011".

I've been wrestling with this one for a while and the closest examples I can find involve comparing two tables.

like image 367
aspekt Avatar asked Mar 24 '26 20:03

aspekt


1 Answers

Using LEFT JOIN/IS NULL

   SELECT a.member
     FROM YOUR_TABLE a
LEFT JOIN YOUR_TABLE b ON b.member = a.member
                      AND b.year = 2011
    WHERE a.year = 2010
      AND b.member IS NULL

Using NOT EXISTS

   SELECT a.member
     FROM YOUR_TABLE a
    WHERE a.year = 2010
      AND NOT EXISTS (SELECT NULL
                        FROM YOUR_TABLE b 
                       WHERE b.member = a.member
                         AND b.year = 2011)

Using NOT IN

SELECT a.member
  FROM YOUR_TABLE a
 WHERE a.year = 2010
   AND a.member NOT IN (SELECT b.member
                          FROM YOUR_TABLE b 
                         WHERE b.year = 2011)

Performance

Performance depends on if the columns compared are NULLable (the values can be NULL):

  • if they are NULLable, NOT EXISTS is the best choice.
  • If they are not nullable, in MySQL the LEFT JOIN/IS NULL is the best choice.
like image 80
OMG Ponies Avatar answered Mar 27 '26 09:03

OMG Ponies