I have 3 tables users, user_group, and groups.
users have one to many relationship with groups.
If I want to fetch only those users who don't have group Mathematics.
I have using the following query for this purpose:
SELECT * FROM users
INNER JOIN user_group ON user_group.user_id = user.UserID
INNER JOIN groups ON user_group.group_id = groups.group_id
WHERE groups.Name <> 'Mathematics';
But it is returning multiple records against all Users. Suppose, if I have user John and he joined 3 groups Science, Mathematics and English. In this case, it will return two records of user John. I want to remove user John totally from the list.
You can use NOT EXISTS:
SELECT *
FROM users AS u
WHERE NOT EXISTS (SELECT 1
FROM user_group AS ug
INNER JOIN groups AS g ON ug.group_id = g.group_id
WHERE ug.user_id = u.UserID AND g.Name = 'Mathematics');
Demo here
If you want to do it using joins, then this is a way:
SELECT u.*
FROM users AS u
LEFT JOIN (
SELECT user_id
FROM user_group
INNER JOIN groups
ON user_group.group_id = groups.group_id AND groups.Name = 'Mathematics'
) AS g ON u.UserID = g.user_id
WHERE g.user_id IS NULL
Demo here
SELECT * FROM users
LEFT JOIN user_group ON user.UserID = user_group.user_id
LEFT JOIN groups ON user_group.group_id = groups.group_id
WHERE groups.Name != 'Mathematics';
Related
I have 3 tables: USERS, GROUPS, GROUP_USERS
I need to get a list of users that are in a specific group and all users needs to contain all groups that are members of.
I tried something like this:
select group_concat(g.name) as groups
, u.*
from USERS u
JOIN GROUP_USERS gu
ON gu.USER_ID = u.ID
JOIN GROUPS g
ON g.ID = ug.GROUP_ID
WHERE ug.GROUP_ID = SOMEID
GROUP
BY u.ID
But this will return all users in group with id SOMEID and will concat only that one group that was use for search, even if a users is member of multiple groups.
Thanks.
I see. You want all groups for a subset of users that are in one group. That would be:
SELECT u.*, group_concat(g.name) as groups
FROM USERS u JOIN
GROUP_USERS gu
ON gu.USER_ID = u.ID JOIN
GROUPS g
ON g.ID = gu.GROUP_ID
GROUP BY u.ID
HAVING SUM(g.id = ?) > 0;
In other words, you need to move the filtering to the HAVING clause.
I have a user table, group table, and user_group table for many to many.
I am confused on how I can get the list of all users belonging to a specific group and if the user does not belong to the current group, I still want his record listed with the group field set to NULL.
If I understand correctly, you can do:
select u.*, ug.group_id
from users u left join
user_group ug
on ug.user_id = u.user_id and ug.group_id = <the group>;
If you do not care about including a group without users, this should work; all groupless users should be collected together under the NULL group_id's userIDs.
SELECT g.group_id, GROUP_CONCAT(u.user_id) AS userIDs
FROM `users` AS u
LEFT JOIN `user_group` AS ug ON u.user_id = ug.user_id
LEFT JOIN `group` AS g ON ug.group_id = g.group_id
GROUP BY g.group_id
;
Imagine the following table structure:
tb.user tb.usergroups tb.group
id id id
name user_id name
group_id
A user can be in multiple groups through the usergroups table.
I want to search for a user by user name and group name. Speaking in examples: user "Bob" is in "GroupA" and in "GroupB". My query so far:
SELECT *
FROM user u
JOIN usergroups ug ON ug.user_id = u.id
JOIN group g ON ug.group_id = g.id
WHERE u.name = 'Bob' AND g.name != 'GroupA'
This isn't exactly what I want; my result still contains Bob, since he's in "GroupB", but I don't want the result to contain Bob at all.
How to do that?
Thanks
I understand you want to select all users named "Bob" that are not in group A but are in group B. This should do it :
SELECT b.*
FROM (SELECT * FROM user u
JOIN usergroups ug ON ug.user_id = u.id
JOIN group g ON ug.group_id = g.id
WHERE u.name = 'Bob' AND g.name = 'GroupB') b
LEFT JOIN (SELECT userid FROM user u
JOIN usergroups ug ON ug.user_id = u.id
JOIN group g ON ug.group_id = g.id
WHERE u.name = 'Bob' AND g.name = 'GroupA') a
ON a.userid=b.userid
WHERE a.userid is NULL
Check this query as i understand you are looking something like this:
SELECT * FROM user AS u
LEFT JOIN usergroups AS ug ON u.id = ug.user_id
LEFT JOIN groups AS gp ON gp.id = ug.group_id
WHERE u.name = 'Bob'
GROUP by ug.user_id
HAVING count(ug.group_id) = 1 AND gp.name !="GROUPA"
SELECT groups.*
, roles.rol_display_name
, users.usr_fname
FROM groups, groups_roles, roles, users
WHERE groups.id = groups_roles.groups_id and
roles.id = groups_roles.roles_id and
groups.grp_manager_id = users.id
In my query if all the AND conditions are true then only it will show all the records but my requirement is even if manager.id is null it should show all the records with users.usr_fname as null.
Use left join instead of inner join (implicit or otherwise) when you join users table:
SELECT g.*
, r.rol_display_name
, u.usr_fname
FROM groups g
JOIN groups_roles gr on g.id = gr.groups_id
JOIN roles r on r.id = gr.roles_id
LEFT JOIN users u on g.grp_manager_id = u.id
I have 3 tables
Users
COLUMNS User Name, USER ID
Groups
COLUMNS Group Name,Group Id
Users_Group
COLUMNS User ID, Group ID
the User group contains the relation between Users and groups.
I want to select from users and groups to get user names and group names togother.
But I want also to get the users who dont have group where the return value of group name will be null
How to create such SQL in mysql
You need to left join as
select
u.username,
g.group_name
from users u
left join users_group ug on ug.user_id = u.user_id
left join groups g on g.group_id = ug.group_id
select u.username,
g.groupname
from users u
left join user_group ug on u.userid=ug.userid
left join groups g on g.groupid=ug.groupid