数据库是:
Highschooler(身份证,姓名,年级)英语:有一名高中学生,具有唯一身份证和特定年级的名字。
朋友(ID1,ID2)英语:ID1的学生是ID2学生的朋友。友谊是相互的,所以如果(123,456)在朋友表中,那么(456,123)。
喜欢(ID1,ID2)英语:ID1的学生喜欢ID2的学生。喜欢某人不一定是相互的,所以如果(123,456)在Likes表中,则不能保证(456,123)也存在。
任务是:找到只有同一年级朋友的学生的姓名和成绩。返回按年级排序的结果,然后按每个年级的名称返回。
一个命令是:
select distinct name, grade
from Highschooler s1
where not exists (select * from Highschooler s2 join Friend on (Friend.ID2 = s2.ID)
where s1.ID = Friend.ID1
and s2.grade <> s1.grade)
order by grade, name
第二个命令是:
select distinct name, grade
from Highschooler s1 join Friend on (Friend.ID1 = s1.ID)
where not exists (select * from Highschooler s2
where Friend.ID2 = s2.ID
and s2.grade <> s1.grade)
order by grade, name
这两个命令都表示我们希望只与同一年级的朋友一起找出Highschooler。但结果却不同。哪一个是正确的,什么是另一个告诉我们的?如果一些专家可以提供一些解释,我将非常感激,
答案 0 :(得分:0)
如果您想与朋友一起找到Highscooler并且相同等级,我认为您需要这个:
select distinct s1.name, s1.grade
from Highschooler s1
join Friend on (Friend.ID1 = s1.ID or Friend.ID2 = s1.ID)
join Highschooler s2 on ((Friend.ID1 = s2.ID and Friend.ID2 = s1.ID) or (Friend.ID1 = s1.ID and Friend.ID2 = s2.ID)) /* sent or received request */
where s1.grade = s2.grade /* same grade */
order by s1.grade, s1.name
答案 1 :(得分:0)
我会将此视为聚合。我发现更容易遵循逻辑。拿friend
表查找每个朋友的成绩。然后由第一个朋友聚合并使用having
子句来确定是否有任何朋友来自其他成绩:
select hs1.*
from friend f join
highschooler hs1
on f.id1 = hs1.id join
highschooler hs2
on f.id2 = hs2.id
group by hs1.id
having sum(hs1.grade <> hs2.grade) = 0;