添加缺失行的默认值(学生和科目的组合)

时间:2017-09-17 18:11:51

标签: sql postgresql join left-join cross-join

我有一张桌子,可以容纳某些科目的学生成绩。

P.c

STUDENT_GRADES

我还有另一张表格,其中包含主题列表。

id | studentid | subjectid | grade ----------------------------------- 1 | 1 | 1 | A+ 2 | 1 | 2 | A 3 | 1 | 3 | A- 4 | 2 | 2 | A 5 | 2 | 3 | A- 6 | 3 | 2 | B 7 | 4 | 3 | B+

SUBJECTS

现在我必须以下列格式检索结果。

subjectid | subjectname ----------------------------- 1 | Maths 2 | Science 3 | History

FORMATTED_GRADES

studentid | subjectid | grade ----------------------------------- 1 | 1 | A+ 1 | 2 | A 1 | 3 | A- 2 | 1 | fail 2 | 2 | A 2 | 3 | A- 3 | 1 | fail 3 | 2 | B 3 | 3 | fail 4 | 1 | fail 4 | 2 | fail 4 | 3 | B+ 包含来自FORMATTED_GRADES的每位学生及其在每个科目中的成绩。如果STUDENT_GRADES中的某个科目没有学生成绩,那么该科目的学生成绩应该会失败。

2 个答案:

答案 0 :(得分:2)

您很可能还有另一个以students为主键的表studentid。在CROSS JOIN中使用它来形成笛卡尔积,每个学生和科目组合都有一行:

SELECT student_id, subject_id, COALESCE(g.grade, 'fail') AS grade
FROM        students       t
CROSS  JOIN subjects       u
LEFT   JOIN student_grades g USING (student_id, subject_id);

最重要的是,这包括所有科目都失败的学生。如果student_grades中没有任何条目,则尝试从student_gradeslike @Gordon demonstrates)中提取独特的学生将错过这些内容。

假设subjects没有名为student_id的列,而students没有列subject_id。否则,您必须使用ON更明确的join syntax而不是USING的快捷方式。

当加入USING子句时,输出表中只有一个(必然相同)连接列的实例,因此我们不需要SELECT列表中的表限定(即使无论如何都会被允许)。

还假设student_grades.gradecharacter data type。否则,您需要显式转换以在COALESCE中获取兼容的数据类型。喜欢:COALESCE(g.grade::text, 'fail')

答案 1 :(得分:1)

使用cross join生成行,使用left joincoalesce()来获取所需的数据:

select st.student_id, su.subject_id,
       coalesce(sg.grade, 'fail') as grade
from (select distinct student_id from student_grades) st cross join
     subjects su left join
     student_grades sg
     on sg.student_id = st.student_id and sg.subject_id = su.subject_id