简体   繁体   中英

How to omit select results based on IDs from another table in mySQL?

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?

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.

Original answer

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 .

Edit

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;

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

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

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