【问题标题】:Add default for missing rows (combinations of students and subjects)为缺失的行添加默认值(学生和科目的组合)
【发布时间】:2018-02-26 06:50:52
【问题描述】:

我有一张表格,其中包含某些科目的学生成绩。

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 的每个学生及其每个科目的成绩。如果STUDENT_GRADES中的某个学科没有学生的成绩,那么该学生在该学科的成绩应该是不及格。

【问题讨论】:

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


    【解决方案1】:

    您很可能有另一个表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_grades (like @Gordon demonstrates) 中提取独特学生的尝试将错过这些。

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

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

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

    【讨论】:

    • 谢谢欧文。这种方法以更短的执行时间提供相同的输出。 +1 详细说明。
    • @MilanTitaju:很好。那么,这不是更好的答案吗?
    【解决方案2】:

    使用cross join 生成行,使用left join 和coalesce() 获取您想要的数据:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-25
      • 2019-06-06
      • 2021-12-29
      • 1970-01-01
      • 2011-08-05
      • 1970-01-01
      • 2013-05-27
      相关资源
      最近更新 更多