MySQL multi table join query - sql

Result needed: The registration number of the cars used by Instructors at the Glasgow, Bearsden office.
The 3 relevant tables I have are; ( I have omitted the non-relevant table information, to simplify this. The database is called easydrive.
No this is not a School or UNI assignment, it is a question from a text book, that we have been given to do so we can learn how to do it, no marks are awarded for this, so you are not doing my homework for me.
**++Staff++**
(PK) Staff ID
(FK) Address ID
(FK) Office
(FK) Car Allocation Number
First Name
Last Name
Position/Title
Office
**++CarAllocation++**
(PK) Car Allocation Number
(FK) Staff ID
(FK) Car ID
**++Car++**
(PK) Car ID
Car Rego
So I need to so a join I think and I think it needs to go something along these lines but am very confused.
SELECT car.rego
FROM car
WHERE staff.office=’Glasgow’ OR ‘Bearsden’
Can someone please fill in the blanks so I can learn how to perform this, do I need to make a new table?

You query most probably needs to look something like this:
SELECT first_name, last_name, car_rego
FROM staff
JOIN carallocation ON (carallocation.staff_id = staff.staff_id)
JOIN car ON (car.car_id = carallocation.car_id)
WHERE staff.office = 'Glasgow' OR staff.office = 'Bearsden';
Note that JOIN is a synonym for an INNER JOIN in MySQL.

I haven't tested it but this should help.
select car.rego
from car
inner join carrallocation ca on ca.carid = car.carid
inner join staff s on ca.staffid = s.staffid
where s.office in ('Glasgow', 'Bearsden')
What you are missing is the joins between the tables. You need to join to the intermediary table to get the relationship between the staff and car tables.

As far as car_allocation is an intermediate table, it's rather better to put it into the FROM clause and JOIN others:
SELECT car.rego
FROM car_allocation A
JOIN car ON A.car_id = car.car_id
JOIN stuff ON A.stuff_id = stuff.stuff_id
AND (staff.office = 'Glasgow' OR staff.office = 'Bearsden' -- OR some another condition, etc)
Pay attention to brackets, they groups conditions.
or
SELECT car.rego
FROM car_allocation A
JOIN car ON A.car_id = car.car_id
JOIN stuff ON A.stuff_id = stuff.stuff_ids
AND staff.office IN ('Glasgow', 'Bearsden')
If you have an enumeration you can use IN operator.
Also JOIN means the same as INNER JOIN. Here's MySQL manual considering JOIN syntax

Related

SQL Server - Question about Inheritance in Database Schemas

I'm having problems understanding the class table inheritance structure that you can implement using database tables. Info on class table inheritance. I have a use case where I have quite different types of persons that I need to model, but they have very minor differences. For example, all of these persons, like Student, Professor and so on, have a surname and a lastname. My first thought was to move theses attributes into a different table inside a base table like you would do in Object Oriented Programming. Here to illustrate further:
Right now, a Professor can only have one person, for example, otherwise it wouldn't make sense in my use case. Also, I have a school table that has two foreign keys, one for the Professor and one for the Student. Lets assume that a school can also have only one professor and one student. This is not the real use case that I have. This example just represents the relation in my real use case which would be too much to explain here.
What I don't understand is how you would collect data based on that. I'm trying to make a SQL Server View where I want to load the Person of the Professor and the Person of the Student from the view point of the School Table. For example:
SELECT
School.professor_id
surname,
lastname
FROM dbo.School AS school
INNER JOIN dbo.Professor as prof
ON school.professor_id = prof.ID
INNER JOIN dbo.Person as prof_person
ON prof.person_id = prof_person.ID
I can output the surname and lastname of the professor, but now I am stuck since I can't figure out how to get the person of the student.
A subtype table typically shares a key with the supertype table, instead of having its own PK and a FK. EG Student.ID is both the PK and the FK.
Then just join Student>Person in addition to Professor>Person, eg
SELECT
School.Id,
prof_person.surname prof_surname,
student_person.surname student_surname
FROM dbo.School AS school
INNER JOIN dbo.Professor as prof
ON school.professor_id = prof.ID
INNER JOIN dbo.Person as prof_person
ON prof.ID = prof_person.ID
INNER JOIN dbo.Student as student
ON school.student_id = student.ID
INNER JOIN dbo.Person as student_person
ON student.ID = student_person.ID
INNER JOIN is associative, so no need for special ordering or parentheses.

How can I take a joined table and use it to reference another table?

I've just started learning SQL and need help with an assignment question. I am asked to look through a dataset about Kickstarter campaigns. I'm asked to find the top 3 categories by amount of backers.
Here is the ER diagram:
ER diagram
In the 'Campaign' Table, there's the 'backers' column, but the 'Category' Table is only related with the Campaign through the 'Sub-Category' Table.
So far, I have been able to Join sub_category.category_id with the sub-category.category_name, but i'm not sure how to take this new Table and join it with Campaign
SELECT C.name AS category_name, SC.category_id, SC.id AS SC_id
FROM Category AS C
JOIN sub_category AS SC ON C.id = SC.category_id
Screenshot
I am hoping to have a table where there is a column for 'Category Name' and 'Backers' and then simply sort it by the number of backers
How should I go about this? Am I on the right track?
SELECT C.name AS category_name, CA.backers
FROM campaign AS CA
JOIN sub_category AS SC
ON CA.sub_category_id =SC.Id
JOIN Category AS C
ON C.id = SC.category_id
order by CA.backers
You can have multiple joins all together in one query.
Secondly there is a connection between Campaign and Sub_Category table which will help to join these two tables.
Later we can then join Category table as these two table has a connection between them based on Category_Id which is a foreign key in sub category table.
At last you can just order by based on Backers.
Let me know if you have any issue or doubt in comments.
And just to take Magnus's answer and rewrite visually, you can better see the hierarchy of the query. See how it closely resembles that of your table relationships
SELECT
C.name category_name,
CA.backers
FROM
campaign CA
JOIN sub_category SC
ON CA.sub_category_id = SC.Id
JOIN Category C
ON SC.category_id = C.id
order by
CA.backers
Notice the indentation to the table its ID is based upon from that prior to it. This way you know which column FROM connecting TO. I have found that if you list the tables in the FROM clause first to show all the HOW tables are related and ON what foreign : primary key relationships, that is the hardest part. Then its just pulling the columns you want after that.

SQL query wrong index when where on join

I have a query with joins that is not using the index that would be the best match and I am looking for help to correct this.
I have the following query:
select
equipment.name,purchaselines.description,contacts.name,vendors.accountNumber
from purchaselines
left join vendors on vendors.id = purchaselines.vendorId
left join contacts on contacts.id = vendors.contactId
left join equipment on equipment.id = purchaselines.equipmentId
where contacts.id = 12345
The table purchaselines has an index on the column vendorId, which is the proper index to use. When the query is run, I know the value of contacts.id which is joined to vendors.contactId which is joined to purchaselines.vendorId.
What is the proper way to run this query? Currently, no index is used on the table purchaselines.
If you are intending to query a specific contact, I would put THAT first since that is the primary basis. Additionally, you had left-joins to the other tables (vendors, contacts, equipment). So by having a WHERE clause to the CONTACTS table forces the equation to become an INNER JOIN, thus REQUIRING.
That said, I would try to rewrite the query as (also using aliases for simplified readability of longer table names)
select
equipment.name,
purchaselines.description,
contacts.name,
vendors.accountNumber
from
contacts c
join vendors v
on c.id = v.contactid
join purchaselines pl
on v.id = pl.vendorid
join equipment e
on pl.equipmentid = e.id
where
c.id = 12345
Also notice the indentation of the JOINs helps readability (IMO) to see how/where each table gets to the next in a more hierarchical manner. They are all regular inner JOIN context.
So, the customer ID will be the first / fastest, then to vendors by that contact ID which should optimize the join to that. Then, I would expect the purchase lines to have an index on vendorid optimizing that. And finally, the equipment table on ITs PK.
FEEDBACK Basic JOIN clarification.
JOIN is just the explicit statement of how two tables are related. By listing them left-side and right-side and the join condition showing on what relationship is between them is all.
Now, in your data example, each table is subsequently nested under the one prior. It is quite common though that one table may link to multiple other tables. For example an employee. A customer could have an ethnicity ID linking to an ethnicity lookup table, but also, a job position id also linking to a job position lookup table. That might look something like
select
e.name,
eth.ethnicity,
jp.jobPosition
from
employee e
join ethnicitiy eth
on e.ethnicityid = eth.id
join jobPosition jp
on e.jobPositionID = jp.id
Notice here that both ethnicity and jobPosition are at the same hierarchical level to the employee table scenario. If, for example, you wanted to further apply conditions that you only wanted certain types of employees, you can just add your logical additional conditions directly at the location of the join such as
join jobPosition jp
on e.jobPositionID = jp.id
AND jp.jobPosition = 'Manager'
This would get you a list of only those employees who are managers. You do not need to explictily add a WHERE condition if you already include it directly at the JOIN/ON criteria. This helps keeping the table-specific criteria at the join if you ever find yourself needing LEFT JOINs.

Complex SQL Query with Dead Ends and 7 Tables

I was tasked with creating a complex query that incudes all of the data from all of the tables minus the Keys. I am having an issue with the dead end tables and how to circle back around to include the data of the connecting table. I need to select columns DivisionName, ProgramName, ProgramChairFName, ProgramChairLName, CourseID, OutcomeDescription from the listed tables.
SQL Diagram
The 'dead-ends' aren't really dead-ends. When you join all the tables by the appropriate keys, you'll get an assembly of the information you want.
Consider a really simple example:
table person
id name
1 Alice
table pet
id person_id animal
1 1 cat
table hobby
id person_id activity
1 1 dancing
Here, the two tables pet and hobby link to the person table via the person_id key.
In your thinking, "pet" could be considered a "dead-end" because it doesn't link to hobby. But it doesn't need to. The query:
SELECT name, animal, activity
FROM person
JOIN pet ON person.id = pet.person_id
JOIN hobby ON person.id = hobby.person_id;
creates the correct joins back to the person table. It's not a linear path (person -> pet -> hobby). The nature of the joins are specified by the "ON" part of the query. You can see this simple example works here: http://sqlfiddle.com/#!9/02c94b/1
So, in your case, you can have a series of JOINs:
SELECT [all the columns you want]
FROM Division d JOIN Program p
ON d.DivisionKey = p.DivisionKey
JOIN ProgramChairMap pcm
ON p.ProgramKey = pcm.ProgramKey
JOIN ProgramChair pc
ON pcm.ProgramChairKey = pc.ProgramChairKey
JOIN Course c
ON p.ProgramKey = c.ProgramKey
JOIN CourseOutcome co
ON c.CourseKey = co.CourseKey
JOIN Outcome o
ON co.OutsomeKey = o.OutcomeKey

SQL Statement querying same table 2 times

Ok, I've got brain cells melting at an alarming rate on this SQL statement. Not my database, but I've been tasked with extracting data. So here's what I'm dealing with...
It is medical data. We have a database where ALL of the people are listed in one table- patients, as well as doctors. Each person has a unique PersonID. Let's just start with the Person table:
Person:
PersonID, PersonType, LastName, FirstName
I have another table that is hospital admissions.
Admissions:
AdmissionID, PersonID and PrimaryMD
where the Primary MD is the same as the Person ID for a doctor.
I need to extract each Admission, with the last name, and then the first name of the patient, but then I need to go back, based on the PrimaryMD identifier and use that value to pull the last name and first name of the doctor so that my results look like:
Admission | PatientLastName | PatientFirstName | DoctorLastName | DoctorFirstName
Ultimately, I'll need to pull address information for both the patient, and the doctor which is all stored in an address table with the same PersonID as in the person table, and then pull the doctor's address using the primarymd against the person table. But I can't figure how to write two queries in the same statement against these similar columns. I tried using aliases, and some left and inner joins and even a union, but I can't seem to get things right.
Any assistance would be hugely appreciated.
Try this:
SELECT
a.AdmissionID,
pat.LastName AS PatientLastName,
pat.FirstName AS PatientFirstName,
doc.LastName AS DoctorLastName,
doc.FirstName AS DoctorFirstName
FROM Admissions a
INNER JOIN Person pat
ON a.PersonID = pat.PersonID
INNER JOIN Person doc
ON a.PrimaryMD = doc.PersonID
For getting addresses use the same steps:
SELECT
a.AdmissionID,
pat.LastName AS PatientLastName,
pat.FirstName AS PatientFirstName,
doc.LastName AS DoctorLastName,
doc.FirstName AS DoctorFirstName
FROM Admissions a
INNER JOIN Person pat
ON a.PersonID = pat.PersonID
INNER JOIN Person doc
ON a.PrimaryMD = doc.PersonID
INNER JOIN Addresses addPat
ON pat.PersonID = addPat.PersonID
INNER JOIN Addresses addDoc
ON doc.PersonID = addDoc.PersonID