How to concatenate SQL queries across 3 tables - mysql

I have 3 tables in my database as follows:
labs
id
lab_name
lab_owner_id (references id in labs_members table)
lab_manager_id (references id in labs_members table)
labs_members
id
person_id (references id in labs_person table)
labs_person
id
first_name
last_name
I need to construct a query to get all of the information from the labs table including the first and last names of the lab owner and lab manager.
I've tried variations of the following query:
SELECT labs.id, labs.lab_name, labs.lab_owner_id, labs.lab_manager_id
FROM labs
LEFT JOIN labs_members on labs.lab_owner_id = labs_members.id
LEFT JOIN labs_members on labs.lab_manager_id = labs_members.id
LEFT JOIN labs_person on labs_person.id = labs_members.person_id
ORDER BY labs.lab_name ASC
However, I haven't had any success getting both the lab manager and lab owner names at the same time. I get an error, or either the lab manager name OR the lab owner name (but not both).
Any assistance is greatly appreciated. Thanks!

You are very very close. One more join to the person table and some table aliases and you'll be there:
SELECT labs.id, labs.lab_name, labs.lab_owner_id, labs.lab_manager_id, owner_person.first_name, owner_person.last_name, manager_person.first_name, manager_person.last_name
FROM labs
LEFT JOIN labs_members as owner on labs.lab_owner_id = labs_members.id
LEFT JOIN labs_members as manager on labs.lab_manager_id = labs_members.id
LEFT JOIN labs_person as owner_person on owner_person.id = owner.person_id
LEFT JOIN labs_person as manager_person on manager_person.id = manager.person_id
ORDER BY labs.lab_name ASC

Related

Optimize multiple join same table

I have two tables: student, address.
address includes id and location
student includes id, name, roommate_id, location_id.
I need to find student's info with student location and roommate location.
I have used the query:
SELECT
student.name as name, stulocation.location as address,
roommate.name as roommate_name, rmatelocation.location as roommate_address
FROM student
LEFT JOIN student as roommate ON student.roommate_id = roommate.id
LEFT JOIN location as stulocation ON student.location_id = stulocation.id
LEFT JOIN location as rmatelocation ON roommate.location_id = rmatelocation .id
I have joined the same table location twice. Is there any better solution to it, instead of querying same table 2 time?

How to Join three tables properly

The main table has 4 columns:
User Activity Table
userActivityId userId therapistId activityId
1 1 1 1
Each of these columns is a table and these values are all foreign keys.
Basically im trying to run a query that will join to the users table and pull their first and last name based off the user Id.Same thing with therapist - join to the therapist table, pull first + last name.And finally Join to the Activity table and pull the activity name and path from the activity Id
The other tables look like this:
User Table
userId fName lName
Therapist Table
therapistId therapistFirstName therapistLastName
Activity Table
activityId activityTitle activityPath
So far my query looks like
SELECT
User_Activities.userId,
User_Activities.therapistId,
User_Activities.activityId,
Activities.activityTitle,
Activities.activityPath,
Users.fName,
users.lName,
Therapists.therapistFirstName,
Therapists.therapistLastName
FROM
User_Activities
INNER JOIN Users
ON User_Activities.userId = Users.userId
INNER JOIN Therapists ON
User_Activities.therapistId = Therapists.therapistId
INNER JOIN Activities ON
Activities.activityId = User_Activities.userActivityId
WHERE
User_Activities.userId = 1;
When I run this query It only returns 1 row as a result. However there are two activities in the User_Activites table assigned to userId 1.
If I change : INNER JOIN Activities ON
Activities.activityId = User_Activities.userActivityId
from an INNER JOIN to the LEFT JOIN it will display the second row, however the activityTitle and activityPath will be displayed as NULL in the second row.
userActivityId userId therapistId activityId activityId activityTitle activityPath fName lName therapistFirstName therapistLastName
1 1 1 1 1 Brain GZZ0zpUQ S C M D
11 1 1 1 NULL NULL NULL S C M D
You have pretty much answered your question. The second activity does not have a valid ActivityId.
If you want all activities for a user, then you should phrase the query as:
SELECT . . .
FROM Users u LEFT JOIN
User_Activities ua
ON ua.userId = u.userId LEFT JOIN
Therapists t
ON ua.therapistId = t.therapistId LEFT JOIN
Activities a
ON a.activityId = ua.userActivityId
WHERE u.userId = 1;
You want to start with the table where you want to keep all the rows. Then use LEFT JOIN to bring in other tables.
Two other changes of note:
Table aliases are used to simplify reading and writing the query. The SELECT needs to change to use the aliases.
The WHERE clause refers to the Users table rather than UserActivities.

Mysql: count and group unique emails in associated tables by polymorphic join

The relevant part of my schema (Mysql 5.6.24) is thus:
table: training_event_invitees
registered (tinyint)
invitee_id (id)
invitee_type (varchar)
table: users
id (integer)
email (varchar)
school_id (integer)
table: contacts
id (integer)
email (varchar)
school_id (integer)
table: schools
id (integer)
email (varchar)
I want to try to do the following: get all the training_event_invitees that have registered set to 1, get the associated school, user and contact records, and then group them by school_id, and return the school id and the count of unique email addresses from that school.
training_event_invitees has a two-column foreign key, using invitee_id and invitee_type: invitee_type would be either "School", "User" or "Contact", and references the id field from the corresponding table.
So, algorithmically, it's something like
- get all the registered training_event_invitees
- get all of the associated user, contact and school records
- group these by users.school_id, contacts.school_id or schools.id
- count the number of distinct emails in each group
So, it should return an array like
[
[1234, 6],
[3407, 2]
]
where 1234 and 3407 are values of school_id and 6 and 2 are the count of distinct emails.
I can break this down into a few steps, but there must be a one-hit way to do it. Can anyone help?
One method is to combine the two tables using left join, and then doing the aggregation:
select coalesce(u.school_id, c.school_id) as school_id,
count(distinct coalesce(u.email, c.email)) as num_emails
from training_event_invitees tei left join
users u
on u.id = tei.invitee_id and tei.invitee_type = 'user' left join
contacts c
on c.id = tei.invitee_id and tei.invitee_type = 'contact'
where tei.registered = 1
group by coalesce(u.school_id, c.school_id);
EDIT:
To include the school, follow the same logic:
select coalesce(u.school_id, c.school_id, s.id) as school_id,
count(distinct coalesce(u.email, c.email, s.email)) as num_emails
from training_event_invitees tei left join
users u
on u.id = tei.invitee_id and tei.invitee_type = 'user' left join
contacts c
on c.id = tei.invitee_id and tei.invitee_type = 'contact' left join
schools s
on s.id = tei.invitee_id and tei.invitee_type = 'school'
where tei.registered = 1
group by coalesce(u.school_id, c.school_id, s.id);

MYSQL Join Multiple times on same table

I am trying to pull both owner and editby. Both of those fields are INT. Inside a simple table, for example:
users:
user_id user_name
-----------------
2 johnny
3 mecca
doc:
owner content editby
----------------------
2 misc 3
SQL:
SELECT doc.owner, doc.content, doc.editby, users.user_name
FROM doc
LEFT JOIN
users
ON
users.user_id = doc.owner
WHERE
doc_id = $id
I can grab owner user_name, but I am not sure how to obtain editby on the same table. How do I go about pulling the different user names for different id fields multiple times?
Join the users table twice with different aliases
SELECT doc.owner, doc.content,
e.user_name as editor,
o.user_name as owner
FROM doc
LEFT JOIN users o ON o.user_id = doc.owner
LEFT JOIN users e ON e.user_id = doc.editby
WHERE doc_id = $id

Mysql join query on multiple tables

I have three tables and in those tables these basic fields
contacts
con_id (primary key)
con_name
con_work_id
con_country_id
work
work_id (primary key)
work_company_name
work_country_id
country
country_id (primary key)
country_name
I'm trying to run a query which displays the con_name, work_company_name and then the country name for BOTH the contact and the work company.
I've tried this;
SELECT *
FROM contacts
LEFT JOIN work ON contacts.con_work_id = work.work_id
LEFT JOIN country ON contacts.con_country_id = country.country_id
LEFT JOIN country ON work.work_country_id = country.country_id
But of course this doesn't work because the last join causes a clash with the second one.
I'm almost there, but can't get the query to display the country_name associated with both the contact AND the work company.
I'd appreciate a way forward.
Many thanks,
Wonder
The following should work:
SELECT *
FROM contacts
LEFT JOIN work ON contacts.con_work_id = work.work_id
LEFT JOIN country c1 ON contacts.con_country_id = c1.country_id
LEFT JOIN country c2 ON work.work_country_id = c2.country_id
The trick is to add an alias to the table, so that it is possible to distinguish the two.