using relational databases and sql
DESCRIPTION
Steven Emory Department of Computer Science California State University, Los Angeles. Using Relational Databases and SQL. Lecture 4: Joins Part II. Topics for Today. Self Joins (Pages 84 - 86) Left and Right Joins (Pages 74 - 80) Mixing Inner and Outer Joins (Pages 81 - 82) . - PowerPoint PPT PresentationTRANSCRIPT
Using Relational Databases and SQL
Steven EmoryDepartment of Computer Science
California State University, Los Angeles
Lecture 4:Joins Part II
Topics for Today
Self Joins (Pages 84 - 86)
Left and Right Joins (Pages 74 - 80)
Mixing Inner and Outer Joins (Pages 81 - 82)
Self Joins
A self join is a table that is joined to itself
Typical case is when a foreign key references a primary key in the same table
Non-typical case is when you want to find pairs of things from within the same table
Useful for modelling hierarchical relationships within a single table
Folders: Parent-Child Hierarchy
Employees: Employee Hierarchy
Typical Self Joins
Employee Table:
EmployeeID (primary key)
FirstName
LastName
JobTitle
Salary
SupervisorID (foreign key references EmployeeID)
Typical Self Joins
#1 List all employees (first and last names) who are supervised by no one.#2 List all employees whose supervisors are supervised by no one.#3 List all employees whose supervisor’s supervisors are supervised by no one.
Typical Self Joins
Solutions (for #2 and #3):
SELECT E.FirstName, E.LastNameFROM Employee E JOIN Employee S ON E.SupervisorID = S.EmployeeIDWHERE S.SupervisorID IS NULL;
SELECT E.FirstName, E.LastNameFROM Employee E JOIN Employee S ON E.SupervisorID = S.EmployeeID JOIN Employee SS ON S.SupervisorID = S.EmployeeIDWHERE SS.SupervisorID IS NULL;
Self Joins in the Movie Database
Good news! There are no hierarchical table relationships, so no typical cases
There are, however, some non-typical self join possibilities, dealing with pairings
Self Joins in the Movie Database
Example
-- List all pairs of movie-related people who were born in the same city, state/province, and country. Do not pair any people with themselves and do not list duplicate pairs.
SELECT P1.FirstName, P1.LastName, '...', P2.FirstName, P2.LastNameFROM People P1 JOIN People P2 ON (P1.BirthCity = P2.BirthCity AND P1.BirthStateProvince = P2.BirthStateProvinceAND P1.BirthCountry = P2.BirthCountry)WHERE P1.PersonID < P2.PersonID;
Self Joins in the Movie Database
Alternate (shorter) solution:
-- List all pairs of movie-related people who were born in the same city, state/province, and country. Do not pair any people with themselves and do not list duplicate pairs.
SELECT P1.FirstName, P1.LastName, '...', P2.FirstName, P2.LastNameFROM People P1 JOIN People P2 USING(BirthCity, BirthStateProvince, BirthCountry)WHERE P1.PersonID < P2.PersonID;
Outer Joins: The Problem
Question: Display a list of movie-related people who are not actors.
Outer Joins: The Problem
Question: Display a list of movie-related people who are not actors.
Let’s try an inner join
SELECT FirstName, LastName, MovieID, CharacterNameFROM People P JOIN XRefActorsMovies AON P.PersonID = A.ActorID;
Incorrect! An inner join associates people (in P) with movie characters (in A) for which they played.
Outer Joins: The Problem
Question: Display a list of movie-related people who are not actors.
Let’s try negating the inner join condition
SELECT FirstName, LastName, MovieID, CharacterNameFROM People P JOIN XRefActorsMovies AON P.PersonID <> A.ActorID;
Incorrect as well! An inner join with a negated join condition associates people (in P) with movie characters (in A) for which they did not play.
Outer Joins: The Problem
To solve the problem, we need to know which PersonIDs in the People table ARE NOT IN the ActorID column of the XRefActorsMovies table?
Outer Joins: The Solution
Use an outer join
SELECT FirstName, LastNameFROM People P LEFT JOIN XRefActorsMovies AON P.PersonID = A.ActorIDWHERE ActorID IS NULL;
SELECT FirstName, LastNameFROM XRefActorsMovies A RIGHT JOIN People P ON P.PersonID = A.ActorIDWHERE ActorID IS NULL;
Can't use equi-join
Outer Join Definition
Outer Join Definition
Outer Join = Matching Records (Inner Join) + Zero-Matching Records (Anti Join + NULL)
Provides information about records in one table that ARE and ARE NOT in the second table
Since we must always have a complete table, NULL values are concatenated to the anti join results
Outer Join Visualization
Outer Join Types
Left Join
Every record from the left (first) table will always be listed at least once
If a matching record is found in the right (second) table, it is listed normally (same as inner join)
If there are no matching records to be found in the right (second) table (zero-matching rows), the record from the left table is still reported, albeit it is associated with NULL values in the right table.
Right Join
Same as left join, but swapping left and right
Outer Join Tips
If you need to use an outer join, always use a LEFT JOIN in MySQL
LEFT JOIN is same as RIGHT JOIN
Difference is do you prefer:
Joining left to right? (LEFT JOIN)
Joining right to left? (RIGHT JOIN)
Mathematical expression and the English grammar read from left to right… therefore I always prefer the LEFT JOIN!
Left Join Syntax
Two tables
SELECT attribute_listFROM table1 LEFT JOIN table2ON join_condition;
More than two tables
SELECT attribute_listFROM table1 LEFT JOIN table2 ON join_condition LEFT JOIN table3 ON join_condition ...
*Note that you may also use JOIN USING syntax as well…
Right Join Syntax
Two tables
SELECT attribute_listFROM table1 RIGHT JOIN table2ON join_condition;
More than two tables
SELECT attribute_listFROM table1 RIGHT JOIN table2 ON join_condition RIGHT JOIN table3 ON join_condition ...
*Note that you may also use JOIN USING syntax as well…
More Left/Right Join Syntax
NATURAL JOIN syntax
SELECT attribute_listFROM table1 NATURAL LEFT JOIN table2;
SELECT attribute_listFROM table1 NATURAL RIGHT JOIN table2;
JOIN USING syntax
SELECT attribute_listFROM table1 LEFT JOIN table2 USING(attribute);
SELECT attribute_listFROM table1 RIGHT JOIN table2 USING(attribute);
Outer Join Order
Join order makes a big difference
A LEFT JOIN B is not the same as B LEFT JOIN A
The expression “People (People table) who are not actors (XRefActorsMovies table)” does not say the same thing as, “Actors (XRefActorsMovies table) who are not people (People table)”
Why not?
Only SOME people are actors (A LEFT JOIN B)
However, ALL actors are people (B LEFT JOIN A)
Thus, you will get different results!
Outer Join Order Example
Try it and you will see that you do not get the same results!
Extracting Data From Outer Joins
To extract the “zero-matching” results from an outer join, you must test the primary key (from the opposite side of the outer join) for NULL
For example, for A LEFT JOIN B, to extract the records in A that have no matches in B, you must test the primary key in B (the right table) for NULL in the WHERE clause
Extracting Data From Outer Joins
Extracting Data From Outer Joins
Mixing Inner and Outer Joins
It is OK to mix inner joins with outer joins
Once you start an outer join, you usually have to keep doing outer joins (if you join more tables)
NULL does not match up with anything
Try the following query with mixed join types:
-- List the first and last names of ALL movie-related people along with the titles of any movies that they have starred in. If a person has not acted in any movies, just display their first and last name along with a NULL movie title.
Mixing Inner and Outer Joins
Solution #1: Correct
SELECT FirstName, LastName, TitleFROM People P LEFT JOIN XRefActorsMovies A ON P.PersonID = A.ActorID LEFT JOIN Movies M ON A.MovieID = M.MovieID;
Mixing Inner and Outer Joins
Solution #2: Incorrect
SELECT FirstName, LastName, TitleFROM People P LEFT JOIN XRefActorsMovies A ON P.PersonID = A.ActorID INNER JOIN Movies M ON A.MovieID = M.MovieID;
Sample Problems
#1 Produce a listing of all genres that are not associated with any movie.
#2 Report the first and last names of all movie-related people born in the US who are not producers, directors nor actors.
Sample Solutions
#1
SELECT G.GenreFROM Genres G LEFT JOIN XRefGenresMovies XGM ON G.Genre = XGM.GenreWHERE MovieID IS NULL;
Sample Solutions
#2
SELECT PersonID, FirstName, LastNameFROM People P LEFT JOIN XRefActorsMovies A ON P.PersonID = A.ActorID LEFT JOIN XRefDirectorsMovies D ON P.PersonID = D.DirectorID LEFT JOIN XRefProducersMovies R ON P.PersonID = R.ProducerIDWHERE A.ActorID IS NULL AND D.DirectorID IS NULL AND R.ProducerID IS NULL;