Reputation: 2494
My goal is that I want to get a list of user names in the database from my "users" table, but omit every user whose ID is also in the "projects_users" table where project_id = 1.
In another words, if these are the tables:
table: users
user_id user_name
1 dave
2 matt
3 james
table: projects_users
user_id project_id
1 2
2 2
3 1
This query would return "dave" and "matt" (since "james" is in the users table, but is also associated with project #1, thus he is omitted).
I understand that I should probably be using some form of join, but my current query is not doing it:
SELECT user_name
FROM users
JOIN projects_users ON (
users.user_id != (projects_users.user_id WHERE projects_users.user_id == 1)
)
This result does not work at all, and earlier experiments kept returning multiple copies of every name. Does anyone know of a way to do this without having to turn to a more manual PHP solution?
Upvotes: 1
Views: 307
Reputation: 2494
Final answer, worked perfectly. Maybe it isn't as optimised as some of the other solutions, but it's the only one that gave me valid results every time. For some reason, the other solutions sometimes popped out an unexpected name, or no name at all when they should have. Regardless, this sure beats doing it the long way with PHP.
SELECT user_id, user_name FROM users WHERE user_id NOT IN (SELECT user_id FROM projects_users WHERE project_id = 1)
Thanks everyone for your contributions. I appreciate all of your help and input.
Upvotes: 2
Reputation:
Try the following:
select u.*
from users u
where exists (select null
from projects_users pu1
where u.user_id = pu1.user_id)
and not exists (select null
from projects_users pu2
where u.user_id = pu2.user_id and pu2.project_id = 1)
Alternatively:
select u.*
from users u
join projects_users pu on u.user_id = pu.user_id
group by u.user_id
having max(case when pu.project_id = 1 then 1 else 0 end) = 0
Upvotes: 0
Reputation: 2777
try this:
SELECT DISTINCT
users.user_id,
user_name
FROM
projects_users
RIGHT JOIN
users
ON
users.user_id = projects_users.user_id
WHERE
projects_users.project_id <> 1
OR
projects_users.project_id IS NULL
Upvotes: 1
Reputation: 230306
Utilize the power of a LEFT JOIN
.
SELECT u.*
FROM users u
LEFT JOIN project_users pu ON u.user_id = pu.user_id
WHERE pu.project_id IS NULL OR pu.project_id <> 1;
Unlike JOIN
(which is a shortcut for INNER JOIN
), LEFT JOIN
selects all rows from main table and their matching rows from joined table, BUT if the matching row is not found, a fake one is returned with all fields set to NULL
.
When I re-read the question, it appeared to me that I got it wrong. If you want to filter out only users that are associated with a certain project, then this is a query to use.
SELECT DISTINCT u.user_id, u.user_name
FROM project_users pu
LEFT JOIN users u ON u.user_id = pu.user_id
WHERE pu.project_id <> 1;
Upvotes: 1