MySQL chain inner JOIN error - mysql

When I log a user, I would like to retrieve his personal information such as his classes and teams. I managed to retrieve the classes, but when I try to retrieve the team it doesn't work.
I have 3 tables (users, teams and classes) and 2 join tables (teams_users and classes_users).
Relation below:
classes (id_classe) <--> classes_users (classe_id, user_id ) <--> users (id_user)
teams (id_team) <--> teams_users (team_id, user_id) <--> users (id_user)
This worked
SELECT * FROM classes `c`
INNER JOIN (SELECT * FROM classes_users `cu`
INNER JOIN (SELECT * FROM users WHERE (users.email = 'tata#gmail.com'))
`u` ON (u.id_user = cu.user_id))
`ui` ON (ui.classe_id = c.id_classe)
But when I tried to add another join below it didn't work.
SELECT * FROM teams_users `tu`
INNER JOIN (SELECT * FROM classes `c`
INNER JOIN (SELECT * FROM classes_users `cu`
INNER JOIN (SELECT * FROM users WHERE (users.email = 'tata#gmail.com'))
`u` ON (u.id_user = cu.user_id))
`ui`ON (ui.classe_id = c.id_classe))
`wc` ON (wc.id_user = tu.user_id)

Why all the parentheses and subqueries? I think this is what you are trying to do:
SELECT *
FROM teams_users tu INNER JOIN
users u
ON u.id_user = tu.user_id INNER JOIN
class_users cu
ON u.id_user = cu.user_id INNER JOIN
classes c
ON cu.classe_id = c.id_classe
WHERE u.email = 'tata#gmail.com';

Related

how can I select three tables with join in mysql?

I want join this tables in only query mysql, I'm trying but it doesn't work.
I want get by idtravel as this pseudocode:
select *
from travel t
left join user
left join vehicule
where idtravel = ?
select *
from
(select *
from vehicle v
left join user u on v.user_idv= u.id
select *
from travel t
left join user u on t.user_idt= u.id) as res
select *
from travel t
left join `user` u on u.id = t.user_idt
left join vehicle v on u.id = v.user_idv
where t.idtravel = ?
SELECT user.*, vehicle.name as vehicale_name, travel.* FROM user
left join `vehicle` on vehicle.user_id = user.id
left join `travel` on travel.user_id = user.id
where travel.idtravel = ?
SELECT * FROM user u
LEFT JOIN travel t ON u.id = t.user_idt
LEFT JOIN vehicle v ON u.id = v.user_idv
WHERE t.idtravel = ?;

SELECT data from multiple tables using joins in MySQL

i have follwing tables
USERS :
* id
* name
* role id
* phone
STUDENTS
1: userid ( fk users.id)
2: course_id
STAFF
1: staff_id(fk users.id)
2: course-id
COURSES
1: COURSE_ID
1:COURSENAME
I need to find all accounts associated with a number
I need name,userid,roleid,courseid,corsename,staffid, by providing mobile
i have written this query but this return zero results
SELECT users.name, users.id, staff.user_id, students.course_id, users.role_id, courses.course_title FROM users INNER JOIN students ON users.id = students.user_id INNER JOIN staff ON staff.user_id = users.id INNER JOIN courses ON courses.id = students.course_id WHERE users.phone = '9495990028'
LIMIT 0 , 30
Try union operator:
SELECT name, s.userid, roleid, s.course_id, c.coursename, null
FROM USERS u
INNER JOIN STUDENTS s
INNER JOIN COURSES c
ON s.userid = u.id AND c.course_id = s.course_id
WHERE u.phone = ?
UNION
SELECT name, null, roleid, s.course_id, c.coursename, s.staff_id
FROM USERS u
INNER JOIN STAFF s
INNER JOIN COURSES c
ON s.staff_id = u.id AND c.course_id = s.course_id
WHERE u.phone = ?;
For the COURSES table, I check the id with the course_id from students and staff
SELECT name, s.userid, roleid, s.course_id, c.coursename, st.staff_id
FROM USERS u
INNER JOIN STUDENTS s ON s.userid = u.id
INNER JOIN STAFF st ON st.staff_id = u.id
INNER JOIN COURSES c ON c.course_id = s.course_id AND c.course_id = st.course_id
WHERE u.phone = ?

How to write a query to get unique elements from a relation

I have 2 entities with a many to many relation. Users - Roles_Users - Roles
How can write a query that returns to me all the users that only has exactly one role which is the role name "customer". I wrote something like this:
SELECT `users`.* FROM `users`
INNER JOIN `roles_users` ON `roles_users`.`user_id` = `users`.`id`
INNER JOIN `roles` ON `roles`.`id` = `roles_users`.`role_id`
WHERE roles.name not in ('admin' , 'sac', 'superadmin', 'customer_service' , 'supplier');
but it still brought to me users that has more than the role 'customer'.
I need the users that has ONLY the role of 'customer' and nothing else
This is how I would solve it:
SELECT `users`.*
FROM `users`
WHERE id IN
(
SELECT `roles_users`.`user_id`
FROM `roles_users`
INNER JOIN `roles`
ON `roles`.`id` = `roles_users`.`role_id`
GROUP BY `roles_users`.`user_id`
HAVING COUNT(*) = 1 -- only a single role
AND MAX(roles.name) = 'customer' -- and this role is 'customer'
)
Btw, there's no need to use all those backticks:
SELECT *
FROM users
WHERE id IN
(
SELECT roles_users.user_id
FROM roles_users
JOIN roles
ON roles.id = roles_users.role_id
GROUP BY roles_users.user_id
HAVING COUNT(*) = 1 -- only a single role
AND MAX(roles.name) = 'customer' -- and this role is 'customer'
)
Isn't this easier to read (and write)?
Compare role name directly,because using in can get you other non required values
SELECT `users`.* FROM `users` INNER JOIN `roles_users` ON `roles_users`.`user_id` = `users`.`id` INNER JOIN `roles` ON `roles`.`id` = `roles_users`.`role_id` WHERE roles.name ='customer'
Why not just look users with the specific role?
SELECT `users`.* FROM `users`
JOIN `roles_users` ON `roles_users`.`user_id` = `users`.`id`
JOIN `roles` ON `roles`.`id` = `roles_users`.`role_id`
WHERE `roles`.name = 'customer';
Use a NOT EXISTS subquery in the WHERE clause:
SELECT u.*
FROM users u
INNER JOIN roles_users ru ON ru.user_id = u.id
INNER JOIN roles r ON r.id = ru.role_id
WHERE r.name = 'customer'
AND NOT EXISTS (
SELECT *
FROM roles_users ru1
WHERE ru1.user_id = ru.user_id
AND ru1.role_id <> ru.role_id
)
The NOT EXISTS condition will ensure that no other roles are assigned to the user.
A shorter but slower solution could be:
SELECT u.*
FROM users u
INNER JOIN roles_users ru ON ru.user_id = u.id
INNER JOIN roles r ON r.id = ru.role_id
GROUP BY u.id
HAVING GROUP_CONCAT(r.name) = 'customer'

mysql count from joins using 3 tables

i'm trying to build a chat application, in which i have these four tables
chat --id,group_id,body,time_posted[timestamp]
chat_groups --establish id,name for a group
users_groups --link users to a group, also define if user stared this group FIELDS::user_id,group_id,stared[bool]
wall_visit --user_id,group_id,last_visit[timestamp]
the idea is every users join a group, and they post to it in chat.
chat_groups table is just for defining the room, while users_groups is for setting access of members to this group.
wall_visit table is a table that store specific user last time accessed specific group (since its many to many u know..)
now what im trying to establish is to get in one query,
the chat_groups the user in relation with
the count of messages posted to this group since user last login (from settings)
the count of members in this group
the group name
:)
i have been trying to hours now :( best i could come up with
SELECT w.last_visit,access.stared,cg.user_id,u.fullname as username,cg.name as group_name ,cgu.count_members,c.count_msgs,c.time_posted
FROM `chat_groups`cg
inner join chat_groups_users access on (access.group_id = cg.id and access.user_id = ?)
left outer join users u on u.id = cg.user_id
left join wall_visit w on w.group_id = cg.id
left join (select count(*) as count_members,group_id from group_users group by group_id) cgu on cgu.group_id = cg.id
left join (SELECT count(wv.id) as count_msgs,c.group_id,c.time_posted FROM chats c
left outer join `wall_visit` wv on (wv.group_id is not null and c.group_id = wv.group_id and c.time_posted > wv.last_visit)
group by c.group_id) c on c.group_id = cg.id
where cg.user_id = 1
this query is working ..ehh, my main problem is with the count of the messages in the group since last_visit.
what is the best methode to get message_count to work :( ??
can this query be optimized more?
Thanks SO community :)
My 2nd attempt
SELECT w.last_visit,access.stared,cg.user_id,u.fullname as username,cg.with_id,uu.fullname as with_name,cg.name as group_name ,cgu.count_members,c.count_msgs,c.time_posted
FROM `chat_groups`cg
inner join chat_groups_users access on (access.group_id = cg.id and access.user_id = 1)
left outer join users u on u.id = cg.user_id
left join wall_visit w on w.chat_id = cg.id
left outer join users uu on uu.id = cg.with_id
left join (select count(*) as count_members,group_id from chat_groups_users group by group_id) cgu on cgu.group_id = cg.id
left join (
SELECT group_id,count(c.id) as count_msgs,time_posted FROM `chats` c inner join wall_Visit wv on wv.chat_id = c.group_id where c.id > wv.last_visit group by c.group_id
) c on c.group_id = cg.id
where cg.user_id = 1
this should fix you count message problem
SELECT
`cg`.`user_id`, `cg`.`with_id`, `cg`.`name` AS `group_name`,
`access`.`stared`,
`u`.`fullname` AS `username`,
`w`.`last_visit`,
`uu`.`fullname` AS `with_name`,
`cgu`.`count_members`,
`c`.`count_msgs`, `c`.`time_posted`
FROM `chat_groups` AS `cg`
INNER JOIN `chat_groups_users` AS `access`
ON (`access`.`group_id` = `cg`.`id` AND `access`.`user_id` = `cg`.`user_id`)
LEFT OUTER JOIN `users` AS `u`
ON (`u`.`id` = `cg`.`user_id`)
LEFT JOIN `wall_visit` AS `w`
ON (`w`.`chat_id` = `cg`.`id`)
LEFT OUTER JOIN `users` AS `uu`
ON (`uu`.`id` = `cg`.`with_id`)
LEFT JOIN (
SELECT COUNT(*) AS `count_members`, `group_id`
FROM `chat_groups_users`
GROUP BY
`group_id`
) AS `cgu`
ON (`cgu`.`group_id` = `cg`.`id`)
LEFT JOIN (
SELECT count(`c`.`id`) AS `count_msgs`, `c`.`time_posted`
FROM `chats` AS `c`
INNER JOIN `wall_visit` AS `wv`
ON (`wv`.`chat_id` = `c`.`group_id`)
WHERE
`c`.`time_posted` > `wv`.`last_visit`
GROUP BY
`c`.`group_id`
) AS `c`
ON (`c`.`group_id` = `cg`.`id`)
WHERE `cg`.`user_id` = 1
otherwise u have to setup a fiddle

Query for correlated tables

I am currently trying to run a query that will show all tables that correlate with each other. I did not make the table design. So I am running into some trouble in making: It's not clear how office_hours table correlates with schedule table? Overall how can I display properly all tables that correlate through a query?
SELECT *
FROM schedule
INNER JOIN semester ON schedule.semester_id = semester.id
INNER JOIN office_hours ON office_hours.id = schedule.???
I think ID from table schedule is only an auto_increment column and the proper way to join schedule from office_hours is office_hours.schedule_id = schedule.semester_id.
select *
from schedule
inner join semester
on schedule.semester_id = semester.id
inner join office_hours
on office_hours.schedule_id = schedule.semester_id
UPDATE 1
select *
from schedule
inner join semester
on schedule.semester_id = semester.id
inner join office_hours
on office_hours.schedule_id = schedule.semester_id
INNER JOIN faculty
ON faculty.id = office_hours.faculty_id
INNER JOIN Section
ON Section.faculty_ID = faculty.id AND
Section.Schedule_ID = Schedule.ID
INNER JOIN class
ON Class.ID = Section.Class_ID
INNER JOIN major_class_br
ON major_class_br.class_ID = Class.ID
INNER JOIN major_minor
ON major_class_br.major_minor_id = major_minor.ID
it is assumed that all ID or linking columns exists on each table that is why INNER JOIN was used. Otherwise, use LEFT JOIN.
You must use the id, which is in both tables:
...
inner join office_hours on office_hours.schedule_id = schedule.id;
Tryu this:
SELECT *
FROM
SCHEDULE
INNER JOIN semester
ON schedule.semester_id = semester.id
INNER JOIN office_hours
ON office_hours.schedule_id = schedule.id