我在MySQL数据库中有几个名为course
、student
和students_in
的表。
- 课程**
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
- 学生**
id name
2 Sally
1 Bob
17 Robert
9 Pierre
12 Sydney
41 James
22 William
5 Mary
3 Robert
92 Doris
6 Harry
- 学生_在**
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
这里有一个小提琴:http://sqlfiddle.com/#!17/8d86ee/34
我的目标是让以下学生获得id
和name
:
1.与Sally一起参加过课程(即"一级"关系),或
1.与Sally一起上过课的人一起上过课(即"二级"关系),或
1.与曾与Sally一起上过课的人一起上过课(即"第三关系"关系)
基本上,我们要找的是与莎莉的一级、二级和三级关系。
下面是对这一过程的描述:
由于Sally选修了课程ID 3和212,所需的结果将如下所示(不是上面的彩色表格,我提供该表格是为了说明所涉及的逻辑):
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
我试图通过使用公共表表达式(CTE)查询一级关系来解决这个问题,并且可能可以使用两个额外的CTE来获得二级和三级关系,但是,这感觉像是一种非常不优雅的方法。
有人能用一种优雅的方法来解决这个问题吗?
谢谢大家!
3条答案
按热度按时间h9vpoimq1#
您可以使用递归
cte
:See fiddle.
6l7fqoea2#
有点冗长,但也比您的尝试更一般化,因为您可以控制深度。
一些防御性补充:1.在学生表上进行左连接,以防那里没有R.I.。2.从结果中过滤掉Sally(不关心Robert和Sally在一起,然后Sally和Robert在一起)
laawzig23#
根据需要多次重复加入,也不错,但可能不太优雅:)