SQL Query for multiple tables (foreign keys involved) - mysql

I currently have 5 tables in MySQL database. Some of them share foreign keys and are interdependent of each other. I am trying to create a query that will show all the results side by side(major, course, semester, etc). The query I created query it is not displaying my desired results since I have not added the other tables. I am not sure how to implement the other tables. How can I modify the mysql-query to display all the results in order?
Query
select * from course left join major on course.id = majors.id left join majors on courses_major_xref.majors_id = majors.id

Try the following
SELECT * FROM course
INNER JOIN major_courses_xref ON course.id = major_courses_xref.course_id
INNER join majors ON major_courses_xref.majors_id = majors.id
INNER JOIN courses_semester_xref ON course.id = courses_semester_xref.course_id
INNER JOIN semester ON courses_semester_xref.semester_id = semester.id;

I think there is just some order of operations problems in your query, try:
SELECT * from course
LEFT JOIN major_course_xref
ON course.id = major_course_xref.courseID
LEFT JOIN major
ON major.id = major_course_xref.major_id
LEFT JOIN course_semester_xref
ON course.id = course_semester_xref.course_id
LEFT JOIN semester
ON course_semester_xref.semester_id = semester.id

Related

SQL Left Join a Table on a Left Joined Table

Iam currently trying to left join a table on a left joined table as follows.
I have the tables:
accounts (id, vorname, nachname)
projektkurse (id, accounts_id, projektwochen_id)
projektkurs_einzel (id, projektkurse_id)
projektkurs_einzel_zeiten (id, date, shift, projektkurs_einzel_id)
Now I want to get every account and the amount times they have an entry inside of projektkurs_einzel_zeiten, which should also be unique. So having the same date and shift multiple times does not count as multiple entries. The result should also be limited by the column projektwochen_id from the table projektkurse. This column should match a certain value for example 8.
Some Accounts don't have any entries in projektkurse, projektkurs_einzel and projektkurs_einzel_zeiten, this is why my first thought was using LEFT JOIN like this:
SELECT accounts.id, accounts.vorname, accounts.nachname, COUNT(DISTINCT projektkurs_einzel_zeiten.date, projektkurs_einzel_zeiten.shift) AS T
FROM accounts
LEFT JOIN projektkurse on accounts.id = projektkurse.creator_id
LEFT JOIN projektkurs_einzel on projektkurse.id = projektkurs_einzel.projektkurs_id
LEFT JOIN projektkurs_einzel_zeiten ON projektkurs_einzel.id = projektkurs_einzel_zeiten.projektkurs_einzel_id
WHERE projektkurse.projektwochen_id = 8
GROUP BY accounts.id
This query does not achieve exactly what I want. It only returns accounts that have atleast one entry in projektkurse even if they have none in projektkurs_einzel and projektkurs_einzel_zeiten. The Count is obviously 0 for them but the accounts that have no entries in projektkurse are being ignored completly.
How can I also show the accounts that don't have entries in any other table with the Count 0 aswell?
I would recommend writing the query like this:
SELECT a.id, a.vorname, a.nachname,
COUNT(DISTINCT pez.date, pez.shift) AS T
FROM accounts a LEFT JOIN
projektkurse
ON a.id = pk.creator_id AND
pk.projektwochen_id = 8 LEFT JOIN
projektkurs_einzel pe
ON pk.id = pe.projektkurs_id LEFT JOIN
projektkurs_einzel_zeiten pez
ON pe.id = pez.projektkurs_einzel_id
GROUP BY a.id, a.vorname, a.nachname;
Notes:
Your problem is fixed by moving the WHERE condition to the ON clause. Your WHERE turns the outer join into an inner join, because NULL values do not match.
Table aliases make the query easier to write and to read.
It is a best practice to include all unaggregated columns in the GROUP BY. However, assuming that id is unique, your formulation is okay (due to something called "functional dependencies").
You should not use eft join table's column ins where condition this work as inner join
You should move the where condition for a left joined table in the corresponding ON clause
SELECT accounts.id, accounts.vorname, accounts.nachname, COUNT(DISTINCT projektkurs_einzel_zeiten.date, projektkurs_einzel_zeiten.shift) AS T
FROM accounts
LEFT JOIN projektkurse on accounts.id = projektkurse.creator_id
AND projektkurse.projektwochen_id = 8
LEFT JOIN projektkurs_einzel on projektkurse.id = projektkurs_einzel.projektkurs_id
LEFT JOIN projektkurs_einzel_zeiten ON projektkurs_einzel.id = projektkurs_einzel_zeiten.projektkurs_einzel_id
GROUP BY accounts.id

MySQL Search Results Using Inner Joins

I am building a superhero database. I would like to join each individual table together so that the user can search for anything rather than having to do an INNER JOIN every time the user performs a query.
For instance, a user could search for the comic series that the superhero came from and all you would have to do is change the SELECT and the WHERE clause.
This returns a good result when searching for a superhero's power:
SELECT sh.heroName, pwr.name FROM superhero sh
INNER JOIN superheroPower sh_pwr ON sh.id = sh_pwr.superheroID
INNER JOIN power pwr ON sh_pwr.powerID = pwr.id
WHERE sh.heroName = 'Superman';
This returns an empty set:
SELECT sh.heroName, pwr.name FROM superhero sh
INNER JOIN superheroPower sh_pwr ON sh.id = sh_pwr.superheroID
INNER JOIN power pwr ON sh_pwr.powerID = pwr.id
INNER JOIN superheroAffiliation sh_aff ON sh.id = sh_aff.superheroID
INNER JOIN affiliation aff ON sh_aff.affiliationID = aff.id
INNER JOIN superheroComic sh_c ON sh.id = sh_c.superheroID
INNER JOIN comic c ON sh_c.comicID = c.id
INNER JOIN publisher pub ON c.publisherID = pub.id
INNER JOIN comicAuthor c_a ON c.id = c_a.comicID
INNER JOIN author a ON c_a.authorID = a.id
WHERE sh.heroName = 'Superman';
Is there a way to search the database with all of the tables already INNER JOINed together? Should I be doing a LEFT JOIN or a different type of JOIN instead?
If there were no NULLs anywhere (as in, everyone of those links in joins always has something on the other side), that would work.
However, because it is an INNER any cases where one side of the join does not have results will eliminate the rows (non matching rows do not show up in an INNER join).
So to answer your direct question, assuming the key you care about is heroName, you should start from superhero and left join everything else on. If you want to be able to use any field as the key, you should be using full outer on all the joins.

MySQL getting data from 3 tables which are connected by mapping tables

I have the following database example:
The example is pretty much self-explanatory: There are lessons held by teachers at defined time periods (time_start, time_end) each time period -> lesson connection has its own max_students number.
I know want to list all lessons with all information of the 3 tables (and the max_students). I would do it like that (I heard, that joining table like that is the fastest way):
SELECT * FROM lesson, teacher, time, teacher_has_lesson, time_has_lesson
WHERE lesson.lesson_id = teacher_has_lesson.lesson_lesson_id
AND teacher.teacher_id = teacher_has_lesson.teacher_teacher_id
AND lesson.lesson_id = time_has_lesson.lesson_lesson_id
AND time.time_id = time_has_lesson.time_time_id
1.) Is this a good solution if you just want to join 3 tables or are there better ones?
2.) This SQL call will get me only lessons, that have a teacher and a time. I also want to display lessons, that are in the database, but dont have a teacher or time yet. How can I do that?
There's an alternative way of writing this using join syntax. What you have is equivalent to an inner join, where you only see rows where there are matches:
select
*
from
lesson l
inner join
teacher_has_lesson tl
on l.lession_id = tl.lesson_lesson_id
inner join
teacher t
on tl.teacher_teacher_id = t.teacher_d
inner join
time_has_lesson tml
on l.lesson_id = tml.lesson_lesson_id
inner join
time tm
on tml.time_time_id = tm.time_ud
There's another type of join called outer join, where all the rows from one table are shown, and null values supplied if there are no matching values in the other table. It comes in two or three variants. left outer join shows all rows from the first table. right outer join shows all rows from the second table. full outer join shows all rows from both tables. So, for your second query you could use:
select
*
from
lesson l
left outer join
teacher_has_lesson tl
on l.lession_id = tl.lesson_lesson_id
left outer join
teacher t
on tl.teacher_teacher_id = t.teacher_d
left outer join
time_has_lesson tml
on l.lesson_id = tml.lesson_lesson_id
left outer join
time tm
on tml.time_time_id = tm.time_ud

Working with complicated joins in MySQL

Here is the schema of the database I'm working with - [redacted]
I'm trying to come up with 2 different queries for 2 different result sets -
Sales representatives with the highest sales
Sales representatives with the highest sales grouped by managerId
I've had some luck with the 1st query; this is what I came up with:
SELECT
SUM(`products`.`cost`) AS `Sale`
, `employees`.`firstName`
FROM
`d2dpro`.`sales_reps`
, `d2dpro`.`products`
INNER JOIN `d2dpro`.`employees`
ON (`sales_reps`.`employeeId` = `employees`.`employeeId`)
INNER JOIN `d2dpro`.`sold_products`
ON (`products`.`productId` = `sold_products`.`productId`)
INNER JOIN `d2dpro`.`sales`
ON (`sold_products`.`saleId` = `sales`.`saleId`) AND (`sales`.`salesCampId` = `sales_reps`.`saleCampId`)
GROUP BY `employees`.`firstName`;
With this query, I'm stuck with this error:
Error Code: 1054
Unknown column 'sales_reps.saleCampId' in 'on clause'
Any help with this query? And also for the 2nd one?
You are using one table (sales_reps) that is CROSS JOIN-ed with the INNER JOIN of the tables employees, sold_products and sales. To be able to reference sales_reps in that JOIN you should include it as inner join: (the FROM clause should look like this)
FROM `d2dpro`.`products`
INNER JOIN `d2dpro`.`employees`
ON (`sales_reps`.`employeeId` = `employees`.`employeeId`)
INNER JOIN `d2dpro`.`sold_products`
ON (`products`.`productId` = `sold_products`.`productId`)
INNER JOIN `d2dpro`.`sales`
ON (`sold_products`.`saleId` = `sales`.`saleId`)
INNER JOIN `d2dpro`.`sales_reps`
ON (`sales`.`salesCampId` = `sales_reps`.`saleCampId`)

MySQL Multiple Joins in one query?

I have the following query:
SELECT
dashboard_data.headline,
dashboard_data.message,
dashboard_messages.image_id
FROM dashboard_data
INNER JOIN dashboard_messages
ON dashboard_message_id = dashboard_messages.id
So I am using an INNER JOIN and grabbing the image_id. So now, I want to take that image_id and turn it into images.filename from the images table.
How can I add that in to my query?
You can simply add another join like this:
SELECT dashboard_data.headline, dashboard_data.message, dashboard_messages.image_id, images.filename
FROM dashboard_data
INNER JOIN dashboard_messages
ON dashboard_message_id = dashboard_messages.id
INNER JOIN images
ON dashboard_messages.image_id = images.image_id
However be aware that, because it is an INNER JOIN, if you have a message without an image, the entire row will be skipped. If this is a possibility, you may want to do a LEFT OUTER JOIN which will return all your dashboard messages and an image_filename only if one exists (otherwise you'll get a null)
SELECT dashboard_data.headline, dashboard_data.message, dashboard_messages.image_id, images.filename
FROM dashboard_data
INNER JOIN dashboard_messages
ON dashboard_message_id = dashboard_messages.id
LEFT OUTER JOIN images
ON dashboard_messages.image_id = images.image_id
Just add another join:
SELECT dashboard_data.headline,
dashboard_data.message,
dashboard_messages.image_id,
images.filename
FROM dashboard_data
INNER JOIN dashboard_messages
ON dashboard_message_id = dashboard_messages.id
INNER JOIN images
ON dashboard_messages.image_id = images.image_id
I shared my experience of using two LEFT JOINS in a single SQL query.
I have 3 tables:
Table 1) Patient consists columns PatientID, PatientName
Table 2) Appointment consists columns AppointmentID, AppointmentDateTime, PatientID, DoctorID
Table 3) Doctor consists columns DoctorID, DoctorName
Query:
SELECT Patient.patientname, AppointmentDateTime, Doctor.doctorname
FROM Appointment
LEFT JOIN Doctor ON Appointment.doctorid = Doctor.doctorId //have doctorId column common
LEFT JOIN Patient ON Appointment.PatientId = Patient.PatientId //have patientid column common
WHERE Doctor.Doctorname LIKE 'varun%' // setting doctor name by using LIKE
AND Appointment.AppointmentDateTime BETWEEN '1/16/2001' AND '9/9/2014' //comparison b/w dates
ORDER BY AppointmentDateTime ASC; // getting data as ascending order
I wrote the solution to get date format like "mm/dd/yy" (under my name "VARUN TEJ REDDY")
Multi joins in SQL work by progressively creating derived tables one after the other.
See this link explaining the process:
https://www.interfacett.com/blogs/multiple-joins-work-just-like-single-joins/