patternsqlMinor
Implementing EXCEPT functionality for social networking exercise
Viewed 0 times
socialnetworkingexerciseforexceptimplementingfunctionality
Problem
I am taking Stanford's Introduction to Databases Self-Paced online course. I have gone through the videos in the SQL mini-course, and I am having trouble completing the exercises.
The following is the question from the SQL Social-Networking Query Exercises, Question 5:
For every situation where student A likes student B, but we have no
information about whom B likes (that is, B does not appear as an ID1
in the Likes table), return A and B's names and grades.
The database can be found here or download the schema + data.
My answer to this question is as follows:
I want to avoid using the WHERE L1.ID2 NOT IN... part of the query.
In particular, I'd like to use two result sets.
The first being the entire Likes relation:
SELECT *
FROM Likes L1;
Then I'd like to take the results from the following query:
SELECT L2.ID
FROM Likes L2
And then someone filter the first result set such that it only includes the tuples in result set 1 if L1.ID2 is not in result set 2.
I feel like there's a join or maybe set operator that can do this?
The following is the question from the SQL Social-Networking Query Exercises, Question 5:
For every situation where student A likes student B, but we have no
information about whom B likes (that is, B does not appear as an ID1
in the Likes table), return A and B's names and grades.
The database can be found here or download the schema + data.
My answer to this question is as follows:
SELECT H1.name, H1.grade, H2.name, H2.grade
FROM (SELECT * FROM Likes L1
WHERE L1.ID2 NOT IN (SELECT L2.ID1 FROM Likes L2)) F INNER JOIN
Highschooler H1 ON F.ID1 = H1.ID INNER JOIN Highschooler H2 ON F.ID2 =
H2.ID;I want to avoid using the WHERE L1.ID2 NOT IN... part of the query.
In particular, I'd like to use two result sets.
The first being the entire Likes relation:
SELECT *
FROM Likes L1;
Then I'd like to take the results from the following query:
SELECT L2.ID
FROM Likes L2
And then someone filter the first result set such that it only includes the tuples in result set 1 if L1.ID2 is not in result set 2.
I feel like there's a join or maybe set operator that can do this?
Solution
Formatting
Using indentation and line breaks would make your code easier to read. There is no real "standard" so go with what you feel is clearest. I usually go with something that resembles C indentation a bit. Others use a more Java-like indentation. Doesn't matter, as long as it makes it more readable.
It's good practice for aliases to get meaningful names. Making the code shorter is all well and good, and in your case doing a self-
MySQL limitations
There are several things you could do in other RDBMS that MySQL doesn't allow. You could have made a Common Table Expression, declared a Table Variable, and even used
Using indentation and line breaks would make your code easier to read. There is no real "standard" so go with what you feel is clearest. I usually go with something that resembles C indentation a bit. Others use a more Java-like indentation. Doesn't matter, as long as it makes it more readable.
SELECT
H1.name,
H1.grade,
H2.name,
H2.grade
FROM
(
SELECT *
FROM Likes L1
WHERE L1.ID2 NOT IN
(
SELECT L2.ID1
FROM Likes L2
)
) F
INNER JOIN Highschooler H1
ON F.ID1 = H1.ID
INNER JOIN Highschooler H2
ON F.ID2 = H2.ID;F and other aliasesIt's good practice for aliases to get meaningful names. Making the code shorter is all well and good, and in your case doing a self-
JOIN they are necessary; but, your subquery being aliased as F doesn't say much about what it represents.MySQL limitations
There are several things you could do in other RDBMS that MySQL doesn't allow. You could have made a Common Table Expression, declared a Table Variable, and even used
EXCEPT; except, none of those are supported by MySQL. I'm afraid, given the tool, this is about as good as it will get. Perhaps someone else will know of a better way. Only other thing I could think of is using a temp table, but that's totally overkill for something simple like this.Code Snippets
SELECT
H1.name,
H1.grade,
H2.name,
H2.grade
FROM
(
SELECT *
FROM Likes L1
WHERE L1.ID2 NOT IN
(
SELECT L2.ID1
FROM Likes L2
)
) F
INNER JOIN Highschooler H1
ON F.ID1 = H1.ID
INNER JOIN Highschooler H2
ON F.ID2 = H2.ID;Context
StackExchange Code Review Q#80104, answer score: 5
Revisions (0)
No revisions yet.