在SQL中对一张表进行自身右连接

3

这可能很基础但我卡住了!

我有两个表,一个表显示学生在哪些班级,另一个表则显示每位学生所获得的成绩。我想要找出特定班级中没有成绩的学生。

我写了下面这段代码作为起点,它可以找到某个班级里已经有成绩的学生列表:

SELECT mem.student_id, mem.class_id
FROM class_memberships as mem
inner join grades as gr
on mem.student_id = gr.student_id
where mem.class_id = 12 and gr.grade_type = 18

那个方法很有效,但我实际需要的是班级中没有成绩的学生,而不是有成绩的学生。我想我可以按如下方式对成员表进行右联接,但没成功:
SELECT mem.student_id, mem.class_id
FROM class_memberships as mem
inner join grades as gr
on mem.student_id = gr.student_id
right join class_memberships as mem2
on mem.student_id = mem2.student_id
where mem.class_id = 12 and gr.grade_type = 18
and mem.student_id is null

上述查询没有返回任何行,我知道有一个学生没有成绩。我参考了谷歌上的SQL右连接示例得出了以上结果。我猜这不起作用是因为"mem.student_id is null"子句,但是所有谷歌上的提示说我需要它。请帮帮我!我对SQL(和编程一般)还是新手,所以这可能非常基础,但我无法在任何地方找到答案。谢谢 :)

4
如果使用的是 SQL Server 数据库,可以在谷歌上搜索“SQL Server NOT EXISTS”了解更多信息。同时请标记这个问题所涉及的关系型数据库管理系统。 - dfundako
只是提醒一下,没有人使用 RIGHT JOINLEFT JOIN 是可以用的...但通常如果我们想使用 RIGHT JOIN,我们会重写成 LEFT JOIN。从最小的表开始查找所需内容。 - SQLMason
5个回答

1
实际上,您只需要在“grades”上执行“LEFT JOIN”。 “LEFT JOIN”将显示所有“class_memberships”记录,无论是否存在相应的“grades”记录。然后,您可以过滤掉没有成绩的记录。
SELECT mem.student_id, mem.class_id
FROM class_memberships as mem
LEFT JOIN grades as gr ON mem.student_id = gr.student_id
WHERE mem.class_id = 12
AND gr.id IS NULL --I'm not sure what your pk field is for your grades table

太棒了,我不知道我可以做gr.id为null!谢谢你。 - grumpasaurus

1
您可能根本不需要进行三路连接:

SELECT student_id
FROM class_membership
LEFT JOIN grades ON (class_membership.student_id = grades.student_id
    AND class_membership.class_id = grades.class_id)
WHERE grades.student_id IS NULL

class_membership已经列出了所有学生,所以你只需要找出哪些学生没有成绩,这意味着他们在该班级的“grade”条目应为null。


谢谢,我没有理解我试图遵循的指南,所以我没有意识到需要寻找空值等级。感谢您的解释! - grumpasaurus

0
SELECT mem.student_id, mem.class_id
FROM class_memberships as mem
inner join grades as gr
on mem.student_id = gr.student_id
where mem.class_id = 12 
and gr.student_id NOT EXISTS (select student_id from class_memberships where class_membership is null)

0
你所需要的是 NOT EXISTS
SELECT m.student_id, m.class_id
FROM class_memberships m
WHERE m.class_id = 12 AND 
      NOT EXISTS (SELECT 1
                  FROM grades g
                  WHERE g.student_id = m.student_id AND gr.grade_type = 18
                 );

然而,我对你的数据结构非常怀疑。我期望grades不仅有学生的链接,还有班级的链接:

SELECT m.student_id, m.class_id
FROM class_memberships m
WHERE m.class_id = 12 AND 
      NOT EXISTS (SELECT 1
                  FROM grades g
                  WHERE g.student_id = m.student_id AND g.class_id = m.class_id
                 );

不过,我可能误解了数据结构。


0

这会导致它出错

其中mem.class_id = 12且gr.grade_type = 18

为什么要两次连接同一张表?

SELECT mem.student_id, mem.class_id
FROM class_memberships as mem
left join grades as gr
       on mem.student_id = gr.student_id
      and gr.grade_type = 18
where gr.student_id is null
  and mem.class_id = 12 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接