I have tables named course
, student
and students_in
in a MySQL database.
The tables look like this:
course
course_id name
3 Physics
12 English
19 Basket Weaving
4 Computer Science
212 Discrete Math
102 Biology
20 Chemistry
50 Robotics
7 Data Engineering
student
id name
2 Sally
1 Bob
17 Robert
9 Pierre
12 Sydney
41 James
22 William
5 Mary
3 Robert
92 Doris
6 Harry
students_in
course_id student_id grade
3 2 B
212 2 A
3 12 A
19 12 C
3 41 A
4 41 B
212 41 F
19 41 A
12 41 B
3 17 C
4 1 A
102 1 D
102 22 A
20 22 A
20 5 B
50 3 A
12 92 B
12 17 C
7 6 A
Here is a Fiddle: http://sqlfiddle.com/#!9/d3f991/1
My goal is to get the id
and name
of the students who:
- have taken a course with Sally (i.e. "first-degree" relationship), OR
- have taken a course with someone who has taken a course with Sally (i.e. "second-degree" relationship), OR
- have taken a course with someone who has taken a course with someone who has taken a course with Sally (i.e. "third-relationship" relationship)
Essentially, we’re looking for first-, second-, and third-degree relationships to Sally.
Here is a depiction of what this looks like logically:
Since Sally took course IDs 3 and 212, the desired result would look like this (not the colorful table above, which I provided for illustration of the logic involved):
student_id student_name
12 Sydney <-- took course ID 3 with Sally
41 James <-- took course ID 3 and 212 with Sally
17 Robert <-- took course ID 3 with Sally
1 Bob <-- took course ID 4 with James
92 Doris <-- took course ID 12 with James and Robert
102 William <-- took course ID 102 with Bob
Other than using a recursive CTE
, is it possible to get the desired output using a more simplified approach, such as one or more of the following?
JOINS
andsubqueries
- using the
ANY
orIN
operators
Thank you!
3
Answers
You can union the separate degrees and group/order the resulting names:
For completeness, I’d add the recursive approach following with the two steps:
You can generalize how deep you want to go in the filtering clause of the recursive step (
WHERE recursion_depth + 1 <= <N>
).Check the demo here.
Note: looking for a non-recursive query would translate to manually apply base step + recursive step number of join operations, multiplied by the depth value, thing that the DBMS would do with a recursive query in a more natural and clean way.
Use
CTE
s for each of the levels with the operatorIN
.Finally use
UNION
to get all the student ids (without duplicates) and again with the operatorIN
get the students details fromstudent
:See the demo.
If you want to use this solution just for comparison to a recursive query then fine, but it is obvious that this is not the proper way to do it.