子查询和相关查询

时间:2015-06-06 17:22:27

标签: mysql sql sqlite

数据库是:

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。但结果却不同。哪一个是正确的,什么是另一个告诉我们的?如果一些专家可以提供一些解释,我将非常感激,

2 个答案:

答案 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;