我正在做一个 SQL 练习并确定了一个解决方案,但是我觉得在我的解决方案中加入 4 个表是我所做的蛮力方式。
我有以下表格:
Highschooler ( ID, name, grade )
Friend ( ID1, ID2 )
ID1 是 ID2 的共同 friend => 如果 [ID1, ID2]
存在于 Friend
中,那么 [ID2, ID1]
也必须如此
Likes ( ID1, ID2 )
ID1 被 ID2 吸引
问题是:
For each student A who likes a student B where the two are not friends, find if they have a friend C in common (who can introduce them!). For all such trios, return the name and grade of A, B, and C.
我的解决方案:
Select H1.name, H1.grade, H2.name, H2.grade, H3.name, H3.grade
FROM Highschooler H1, Highschooler H2, Highschooler H3,
-- Following table contains each trio of A, B, C
(Select L.ID1 as ID1, L.ID2 as ID2, F.ID2 as ID3
FROM (SELECT * FROM Likes EXCEPT SELECT * FROM Friend) as L, Friend as F
WHERE L.ID1 = F.ID1 AND -- Found a potential friend C of A
F.ID2 in (SELECT ID2 FROM Friend WHERE Friend.ID1 = L.ID2)) -- Does potential C appear in list of B's friends?
WHERE H1.ID = ID1 and H2.ID = ID2 and H3.ID = ID3
我觉得
Highschooler H1, Highschooler H2, Highschooler H3
声明是我的“蛮力”。SELECT
第一个 FROM
中的声明正确找到 [A.ID, B.ID, C.ID]
trios 而语句的其余部分只是获取响应这些 ID 的名称和等级。有没有比我做的 4-way join 更好的方法来做这个获取?
最佳答案
此查询应该给出相同的结果,但使用的语法略有不同。最后,您需要加入 Highschooler 三次,因为您需要三个不同人的姓名和年级 - 对此没什么可做的。
select
liker.name, liker.grade,
liked.name, liked.grade,
common_friend.name, common_friend.grade
from likes l
-- student1 who likes
join Highschooler liker on liker.ID = l.ID1
-- student2 who is liked
join Highschooler liked on liked.ID = l.ID2
-- friends on student1
join Friend f on l.ID1 = f.ID1
-- that are in student2s friends
and f.ID2 in (select id1 from friend where id2 = l.ID2)
-- the common friend
join Highschooler common_friend on common_friend.ID = f.ID2
-- student1 and student2 can't be friends
where not exists (select 1 from Friend where ID1 = l.ID1 and id2 = l.ID2)
关于sql - 在具有较少连接的关系中找到三个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32418519/