views:

66

answers:

1

Hello,

I have a schema like this:

// table badge_types
id | name
+++|++++++++++
1  | mentor
2  | proctor
3  | doctor

// table badges
id | badge_type_id | user_id     
+++|+++++++++++++++|++++++++
1  | 1             | 5
2  | 1             | 6
3  | 2             | 6
4  | 3             | 6
5  | 2             | 19
6  | 3             | 20

What I want to do, is select all badge_types that a particular user has not yet gotten. In the above example, calling the query for:

user_id = 5 returns badge_type_id 2 and 3

user_id = 6 returns empty set (user got all of them already)

user_id = 19 returns badge_type_id 1 and 3

I can do this with an INTERSECT clause. But I'm wondering if it can be done with a simple JOIN? Any help would be appreciated.

+10  A: 

Using LEFT JOIN/IS NULL:

   SELECT bt.name
     FROM BADGE_TYPES bt
LEFT JOIN BAGDES b ON b.badge_type_id = bt.id
                  AND b.user_id = ?
    WHERE b.id IS NULL

Using NOT EXISTS

   SELECT bt.name
     FROM BADGE_TYPES bt
    WHERE NOT EXISTS(SELECT NULL
                       FROM BADGES b 
                      WHERE b.badge_type_id = bt.id
                        AND b.user_id = ?)

Using NOT IN

   SELECT bt.name
     FROM BADGE_TYPES bt
    WHERE bt.id NOT IN (SELECT b.badge_type_id
                       FROM BADGES b 
                      WHERE b.user_id = ?)

MySQL

If the columns are not nullable, LEFT JOIN/IS NULL is the best choice. If they are nullable, NOT EXISTS and NOT IN are the best choice.

SQL Server

Mind that on SQL Server, NOT IN and NOT EXISTS perform better than LEFT JOIN /IS NULL if the columns in question are not nullable.

Oracle

For Oracle, all three are equivalent but LEFT JOIN/IS NULL and NOT EXISTS are preferable if columns aren't nullable.

OMG Ponies
Professional answer! Well done!
Bobby B
Thanks for the detailed answer. The first answer is facepalm for me, can't believe I didn't put the AND b.user_id in before. Do you know of any sites that give increasingly harder SQL practice queries? I want to learn it well, but it won't happen with my minimal exposure to it.
Jasie
@Jasie: Google TSQL challenges, but they're SQL Server functionality oriented, which MySQL might not provide. Or hang out on SO, reviewing questions from the past few days...
OMG Ponies
Ok, thanks, I will try that out.
Jasie