mysql JOIN between three tables - mysql

I have 4 tables in my database:
users (id,name)
roles (id,name)
positions (id,name)
position_user (user_id,position_id)
Relationship between users to roles is one to one
Relationship between users positions is many to many
i want to take all users with their role name and list with their positions but i don't know how to structure my query. I think that one of my query must be something like this:
SELECT pu.user_id AS user_id,
group_concat(p.name separator ',') AS list_pos
FROM position_user pu
INNER JOIN positions p
ON p.id = pu.position_id
GROUP BY pu.user_id
And other one must be like this :
SELECT users.id, users.first_name, roles.name
FROM users
JOIN roles
ON users.role_id = roles.id
Can I combine these two in one query and how ?

Try something like this and check the MySQL documentation.
SELECT pu.user_id AS user_id, u.first_name, r.name as rol_name, group_concat(p.name separator ',') AS list_pos
FROM position_user pu
INNER JOIN positions p ON p.id = pu.position_id
INNER JOIN users u ON u.id = pu.uder_id
INNER JOIN roles R ON u.role_id = r.id
GROUP BY pu.user_id, u.first_name, r.name

Related

GROUP_CONCAT() like function to return fields that don't match?

I have three tables in my database, for the purposes of discussion let's say they are:
USERS
-----
user_id
user_name
ROLES
-----
role_id
role
USER_ROLES
----------
user_role_id
user_id
role_id
I can easily use GROUP_CONCAT() to return a comma separated list of roles the user does have like so:
SELECT u.user_id, u.user_name, GROUP_CONCAT(role) AS roles_held
FROM users u,
roles r,
user_roles ur
WHERE u.user_id = ur.user_id
AND r.role_id = ur.role_id
GROUP BY u.user_id, u.user_name;
What I'd like to do is also return a list of roles the user does not have.
My initial thought was using sub-query then concatenating that, but I can't seem to get that to work. Can someone point me in the right direction?
Thank you!
EDIT: To clarify, the desired output would be a query that returns the user_id, user_name, a concatenated string of the roles the user does have and a concatenated string of the roles the user does not have. So for example:
USER_ID USER_NAME ROLES_HELD ROLES_LACKED
1 Bob User,Writer Editor,Admin
2 Doug User Writer,Editor,Admin
I agree with using a CROSS JOIN here, but it doesn't need to be quite so complicated:
SELECT
u.user_id,
u.user_name,
GROUP_CONCAT(case when ur.user_id is not null then r.role end) AS roles_held,
GROUP_CONCAT(case when ur.user_id is null then r.role end) as roles_lacked
FROM
users u
CROSS JOIN roles r
LEFT JOIN user_roles ur ON
u.user_id = ur.user_id
AND r.role_id = ur.role_id
GROUP BY
u.user_id, u.user_name
You could try to join table role two times The first time to get held roles, the second time to get lacked roles.
SELECT u.user_id,
user_name,
GROUP_CONCAT(DISTINCT r.role) AS role_held,
GROUP_CONCAT(DISTINCT r1.role) AS role_lacked
FROM users u
INNER JOIN user_roles ur
ON u.user_id = ur.user_id
INNER JOIN roles r
ON r.role_id = ur.role_id
INNER JOIN roles r1
ON NOT EXISTS (SELECT 1
FROM user_roles ur1
WHERE user_id = u.user_id
AND role_id = r1.role_id)
GROUP BY u.user_id,
user_name
I've created a demo here

Select distinct didn't work correctly (MySQL)

I have a query like that:
SELECT DISTINCT r.name AS role, r.id AS role_id, u.id AS user_id, concat( u.firstname, '', u.lastname ) AS name
FROM users u
INNER JOIN members m ON u.id = m.user_id
INNER JOIN member_roles mr ON m.id = mr.member_id
INNER JOIN roles r ON r.id = mr.role_id
WHERE m.project_id =11
My goal is to get unique u.id(user_id). Unfortunately, the result show two duplicate u.id from this multiple join. If I remove the last one join(INNER JOIN roles r ON r.id = mr.role_id), this query run correctly. But I didn't know why it was wrong if I add this line to my query. The last one join line is necessary to get the role's name, so I can ignore it. Can someone tell me where I did incorrectly in my query?
Use GROUP BY in your query to get rows with unique user_id.
Then the updated query will be look like the following.
SELECT DISTINCT r.name AS role, r.id AS role_id, u.id AS user_id,
concat( u.firstname, '', u.lastname ) AS name
FROM users u
INNER JOIN members m ON u.id = m.user_id
INNER JOIN member_roles mr ON m.id = mr.member_id
INNER JOIN roles r ON r.id = mr.role_id
WHERE m.project_id =11 GROUP BY user_id
You are missing the fact that users can have multiple roles on a project. Fortunately, MySQL has group_concat() which can bring the multiple values together:
SELECT u.id AS user_id, concat( u.firstname, '', u.lastname ) AS name,
GROUP_CONCAT(r.name) as roles,
GROUP_CONCAT(r.id) as role_ids
FROM users u INNER JOIN
members m
ON u.id = m.user_id INNER JOIN
member_roles mr ON m.id = mr.member_id INNER JOIN
roles r
ON r.id = mr.role_id
WHERE m.project_id = 11
GROUP BY u.id;

MySql join with 2 Tables and 2 join

I have 2 tables:
posts: userid, lastuserid
users: id, name
I need to join posts.userid = users.id and posts.lastuserid = users.id to get username and lastusername.
My query did as below:
SELECT posts. * , users.name, vUsers.name
FROM posts
INNER JOIN users ON users.id = posts.userid
INNER JOIN Users ON vUsers.id = posts.lastuserid
Is there any other (better) way to do this?
Your query is probably correct. I would encourage you to use table aliases that are abbreviations for the things you are looking for:
SELECT p. * , u.name as username, l.name as lastusername
FROM posts p INNER JOIN
users u
ON u.id = p.userid INNER JOIN
users l
ON l.id = p.lastuserid;
Your query has something called vUsers, which is not defined.

mysql left join exists

Tables:
users: id, name
usersFacebookFriends: id, uid, friendUid, name
I need a query to search for friends (name), and check if they exists in the users table, so then they are also on the website registered.
Is this possible with a left join, and if so how?
Thanks.
SELECT ff.id, ff.uid, ff.friendUid, ff.name, u.id, u.name
FROM usersFacebookFriends ff
LEFT JOIN users u
ON ff.name = u.name;
If you want only those that exist:
SELECT ff.id, ff.uid, ff.friendUid, ff.name, u.id, u.name
FROM usersFacebookFriends ff
INNER JOIN users u
ON ff.name = u.name;
If you want only those that don't exist:
SELECT ff.id, ff.uid, ff.friendUid, ff.name, u.id, u.name
FROM usersFacebookFriends ff
LEFT JOIN users u
ON ff.name = u.name
WHERE u.id IS NULL;
I guess this should make a job. If facebook friend is not registered with your site corrsponding joined User table fields will be NULL.
SELECT f.name, u.* FROM usersFacebookFriends AS f
LEFT JOIN users AS u
ON f.friendUid = u.id
WHERE f.uid = 123
Change LEFT JOIN to INNER JOIN if you need to find only those who exist.

Need help with a mysql query

I have a payments table that has the following structure.
**Payments**
id
name
created_by - user_id
closed_by - user_id
**Users**
user_id
name
surname
What is the best way to show both the name and surname of the user who has created and closed the payment file.
The only way i can think this could work would be using a subquery for both(created_by,closed_by fields) thanks
Try this:
SELECT p.id, p.name,
CONCAT (u1.name,' ', u1.surname) created,
CONCAT (u2.name,' ', u2.surname) closed,
FROM payments p INNER JOIN users u1
ON p.created_by = u1.user_id
INNER JOIN users u2
ON p.closed_by = u2.user_id
EDITED: if you want name and surname splitted
SELECT p.id, p.name,
u1.name created_name, u1.surname created_surname,
u2.name closed_name, u2.surname closed_surname,
FROM payments p INNER JOIN users u1
ON p.created_by = u1.user_id
INNER JOIN users u2
ON p.closed_by = u2.user_id
A strict join is not enough, I think you can use joins in the where clause
select name, surname
from
payments p, users u
where
u.user_id = p.created_by
and u.user_id = p.closed_by
You can join to a single table multiple times, but you have to use an alias.
select
p.*,cr.*,cl.*
from
payments p
join users cr
on p.created_by = cr.user_id
join users cl
on p.closed_by = cl.user_id