SELECT data from multiple tables using joins in MySQL - 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 = ?

Related

Get only those rows where column a has as many duplicate entries, as many there is distinctive values in column b

My current query:
select users.id as user_id, opportunities.id as op_id, opportunities.title, certificates.id as cert_id from opportunities
join opportunity_certificates on opportunities.id=opportunity_certificates.opportunity_id
join certificates on opportunity_certificates.certificate_id=certificates.id
join user_certificates on certificates.id=user_certificates.certificate_id
join users on user_certificates.user_id=users.id
where opportunity_certificates.is_required = 1 and
opportunities.id = 1
This produces the table on the picture below.
cert_id column can have values from 1 to 7, depends on the opportunities.id. In the table below, I want the query to return only the rows which have the same user_id but different cert_id, 1 and 2.
If the table had 3 different cert_id, I would want it to return only the rows which have same user_id but different cert_id, 1,2 and 3.
when the cert_id has only one value, query should return all the records with that one value in cert_id. Basically, it should show all users who have all required certificates.
The query has to be in the current format. I experimented with
group by users.id
having count(*) >
but I don't know how to make that comparison dynamic, relative to the count of distinctive values in the cert_id column.
Compare counts with a having condition.
select u.id as user_id --, o.id as op_id, o.title
from opportunities o
join opportunity_certificates oc on o.id=oc.opportunity_id
join certificates c on oc.certificate_id=c.id
join user_certificates uc on c.id=uc.certificate_id
join users u on uc.user_id=u.id
where oc.is_required = 1 and o.id = 1
group by u.id --,o.id,o.title
having count(distinct c.id)=(select count(distinct id) from certificates)
Useful?
with data as (
select users.id as user_id, o.title, c.id as cert_id
from opportunities o
inner join opportunity_certificates oc on oc.opportunity_id = o.id
inner join certificates c on c.id = oc.certificate_id
inner join user_certificates uc on uc.certificate_id = c.id
inner join users u on u.id = uc.user_id
where oc.is_required = 1 and o.id = 1
)
select user_id, min(title) as title, max(cert_id) as num_certs
from data
group by user_id
having count(cert_id) = (select max(cert_id) from data);
I'm assuming that cert_id values start and 1 and run sequentially. You could also use count(distinct ...) in the having clause but it guess it's debatable which ones expresses you intent more clearly.
If your version of MySQL doesn't support CTEs then you should be able to just drop that whole subquery into the having clause as well.
select u.id as user_id, min(o.title) as title, max(c.cert_id) as num_certs
from opportunities o
inner join opportunity_certificates oc on oc.opportunity_id = o.id
inner join certificates c on c.id = oc.certificate_id
inner join user_certificates uc on uc.certificate_id = c.id
inner join users u on u.id = uc.user_id
where oc.is_required = 1 and o.id = 1
group by u.id
having count(c.cert_id) = (
select max(c.cert_id)
from opportunities o
inner join opportunity_certificates oc on oc.opportunity_id = o.id
inner join certificates c on c.id = oc.certificate_id
inner join user_certificates uc on uc.certificate_id = c.id
inner join users u on u.id = uc.user_id
where oc.is_required = 1 and o.id = 1
);
Here's another one that might work if you have window functions available. (It might work with Laravel better?):
select *
from (
select users.id as user_id, o.title,
count(distinct c.id) over (partition by u.id) as user_certs,
max(c.id) over () as total_certs
from opportunities o
inner join opportunity_certificates oc on oc.opportunity_id = o.id
inner join certificates c on c.id = oc.certificate_id
inner join user_certificates uc on uc.certificate_id = c.id
inner join users u on u.id = uc.user_id
where oc.is_required = 1 and o.id = 1
) t
where user_certs = total_certs;

How to JOIN three tables with IN array filter, but still get all the rows from third table

I have Users and Skills table connected through UserSkills table for many-to-many relation. Here is what's in the tables:
Users (id, username)
Skills (id, name)
UserSkills (user_id, skill_id)
I have an array of skills that I am looking for ['C#', 'SQL']. So I am doing join with IN filtering operation to get only those users that I need.
SELECT (username, GROUP_CONCAT(Skills.name)) FROM Users
JOIN UserSkills ON Users.id = UserSkills.user_id
JOIN Skills ON Skills.id = UserSkills.skill_id AND Skills.name IN ('C#', 'SQL')
GROUP BY Users.id
I want to get same users list but with all their skills, not only those that I am looking for. For instance:
In my case I get: username: 'joe' | skills: 'C#', 'SQL'
I want to get: username: 'joe' | skills : 'C#', 'SQL', 'JavaScript', 'NodeJS'
Please help.
The most straight forward way would be to just join a second time:
SELECT u.username, GROUP_CONCAT(DISTINCT userS.name)
FROM Users AS u
INNER JOIN UserSkills AS us ON u.id = us.user_id
INNER JOIN Skills AS filterS ON filterS.id = us.skill_id AND filterS.name IN ('C#', 'SQL')
INNER JOIN Skills AS userS ON userS.id = us.skill_id
GROUP BY u.id
But you will need the DISTINCT in GROUP_CONCAT as the filter skills will basically cross join with the user skills. Also worth noting is this query gets users with any of the skills specified not all. This is a better solution:
SELECT u.username, GROUP_CONCAT(s.name) AS skils
, COUNT(CASE WHEN s.name IN ('C#', 'SQL') THEN 1 ELSE NULL END) AS matchedSkillCount
FROM Users AS u
INNER JOIN UserSkills AS us ON u.id = us.user_id
INNER JOIN Skills AS s ON s.id = us.skill_id
GROUP BY u.id
HAVING matchedSkillCount > 0 -- You can replace 0 with the number of matches you want
;
...but on very large databases, the above might become costly; a couple other alternatives:
SELECT u.username, GROUP_CONCAT(DISTINCT userS.name)
FROM Skills AS filterS
INNER JOIN UserSkills AS ufs ON filterS.id = ufs.skill_id
INNER JOIN Users AS u ON ufs.user_id = u.id
INNER JOIN UserSkills AS us ON u.id = us.user_id
INNER JOIN Skills AS userS ON us.skill_id = userS.id
WHERE filterS.name IN ('C#', 'SQL')
GROUP BY u.id;
SELECT u.username, GROUP_CONCAT(s.name) AS skils
FROM Users AS u
INNER JOIN UserSkills AS us ON u.id = us.user_id
INNER JOIN Skills AS sON s.id = us.skill_id
WHERE u.id IN (
SELECT DISTINCT ufs.user_id
FROM Skills AS filterS
INNER JOIN UserSkills AS ufs ON filterS.id = ufs.skill_id
WHERE filterS.name IN ('C#', 'SQL')
)
GROUP BY u.id
;
Logically, the WHERE is applied after the joins; but most RDBMS (like MySQL) optimize execution by using the WHERE conditions to minimize the rows joined together.
select USERS.name,GROUP_CONCAT(Skills.name) from USERS join USERSKILLS on users.id =
USERSKILLS.user_id join skills on USERSKILLS.SKILL_ID = skills.ID and users.id in (
select distinct users.id from
users join USERSKILLS on users.id = USERSKILLS.user_id join skills on skills.id = userSkills.skill_id and
Skills.name IN ('C#', 'SQL'))
group by USERS.name;

Select two columns from two different table with multiple join[Mysql]

I have four tables are users(id,name), roles(id,name), members(project_id,user_id,id), and member_roles(member_id, role_id). So how can I select users.name and roles.name from this tables simultaneously(project_id is the condition to select exactly the names what we need)?. I can select users.name and roles.name separately but when I connect two queries, my code was failed. This is the query to get users.name
select users.name from users
inner join members on members.user_id = users.id
where project_id = 1
and here is the query to get roles.name
select roles.name from roles
inner join member_roles on member_roles.role_id = roles.id
join members on members.id = member_roles.member_id
where project_id = 1
You're almost there. Also, to avoid ambiguity, supply an Alias on column Name.
SELECT DISTINCT
u.Name AS member_name,
r.Name AS role_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 = 1
How do you connect 2 queries? How about something like this:
select u.name as user_name, r.name as role_name from users u join members m on m.user_id = u.id join member_roles mr on mr.member_id = m.id join roles r on r.id = mr.role_id where m.project_id = 1;

SQL view all courses for one student

I have 3 tables
table_student
ID, firstname, lastname
table_courses
ID, course_name
table_student_course
ID, student_ID, course_ID, date_taken
All I want to do is list all courses by course_name and date_taken by student with ID=1
Anyone please?
You need to use the JOIN on the table_courses and table_student_course tables and then apply the Order By on cource_name to sort out by course name.And for selecting the particular student apply the Where clause as filter.
SELECT
t.course_name,
tsc.date_taken
FROM
table_courses t INNER JOIN table_student_course tsc
ON t.ID = tsc.course_ID
WHERE
tsc.student_ID = 1
ORDER BY
t.course_name
If you also want to get the students detail from the query then you need to join the 3 tables like below,
SELECT s.firstname, s.lastname, c.course_name, sc.date_taken
FROM table_courses c
INNER JOIN table_student_course sc ON c.ID = sc.course_ID
INNER JOIN table_student s ON sc.student_ID = s.ID
WHERE sc.student_ID = 1
ORDER BY c.course_name
SELECT s.firstname, s.lastname, c.course_name, sc.date_taken
FROM table_courses c
INNER JOIN table_student_course sc ON c.ID = sc.course_ID
INNER JOIN table_student s ON sc.student_ID = s.ID
WHERE sc.student_ID = 1
ORDER BY c.course_name
By using Inner Join on the tables "table_courses" & "table_student_course" we selects all rows from both tables as long as there is a match between the columns in both tables making sure the ids are the same. If the condition is met( student_id=1) then the query will return what is expected.
SELECT course_name, date_taken
FROM table_courses c INNER JOIN table_student_course sc ON c.id = sc.course_id
WHERE sc.student_ID = 1
ORDER BY course_name

Get all userid friends give unnexpected result

lets say:
table users(id, name, ..)
table friends(uid, fid)
How can i get some 33456 user id friends?
SELECT fid idd, name
FROM users,
friends
WHERE uid = 33456
AND fid = id
But would give me unnexpected results
SELECT id, fid, name
FROM users,friends where users.id=friends.fid
WHERE users.id = 33456
SELECT id, fid, name
FROM users
INNER JOIN friends ON users.id=friends.fid
WHERE users.id = 33456
select id,name from users where id in (select fid from friends where uid=33465)
this will return all ID with the name of your friends.
SELECT b.fid, c.name
FROM users a INNER JOIN friends b ON a.id = b.uid
INNER JOIN users c on b.fid = c.id
WHERE a.id = 33456
SELECT u.name,u.id
FROM users u
WHERE u.id IN
(
SELECT f.fid
FROM users u INNER JOIN friends f ON u.id = f.fid
WHERE f.uid = 33456
)