views:

39

answers:

3

How would I query MySQL database to return roles that are still not assigned (like available to him).

With table user_roles:

|user_id|role_id|
|   1   |   1   |
|   1   |   2   | 
|   1   |   4   |
|   1   |   7   |

How can I query roles table to return role name and id of all the roles that are not assigned. role_id: 3,5,8,...

+2  A: 

Try

SELECT *
FROM roles r
WHERE NOT EXISTS (
   SELECT 1
   FROM user_roles ur
   WHERE ur.role_id = r.id
   AND ur.user_id = 1
)
DrewM
Thank you! Much appreciated
LukeP
A: 
SELECT * 
FROM roles 
WHERE roles.id NOT IN (SELECT distinct role_id FROM user_roles)

if you want roles not assigned to user 1.

SELECT * 
FROM roles 
WHERE roles.id NOT IN (SELECT distinct role_id FROM user_roles WHERE NOT user_ID = 1)

Note: This is MUCH faster than the accepted answer, since it only runs the sub-query once and not once for every row in roles.

Hogan
This returns only roles that are not assigned to anybody
LukeP
That is what you asked for. "How can I query roles table to return role name and id of all the roles that are not assigned."
Hogan
See above for not assigned to user 1 -- also my note.
Hogan
There's no need to use `DISTINCT` in the subquery, and it probably runs a bit faster without it. `DISTINCT` is often implemented by sorting the data set.
Bill Karwin
@Bill, Good point -- I was not sure if Distinct was better or worse in this case. Now I know.
Hogan
+1  A: 

I prefer to do this sort of set-complement query by using an outer join, instead of correlated or non-correlated subqueries.

SELECT r.id
FROM roles r
LEFT OUTER JOIN user_roles u 
  ON r.id = u.role_id AND u.user_id = 1
WHERE u.role_id IS NULL;
Bill Karwin