添加缺失行的默认值(学生和科目的组合)
Add default for missing rows (combinations of students and subjects)
我有一个 table,其中包含学生在某些科目中的成绩。
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+
我还有另一个 table 包含主题列表。
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
和 his/her 年级的每个学生。如果STUDENT_GRADES
中某科目没有学生成绩,则该学生该科目成绩应为不及格。
使用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
您很可能还有另一个 table 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
() 中提取唯一学生的尝试将错过那些。
假设 subjects
没有名为 student_id
的列并且 students
没有名为 subject_id
的列。否则你必须使用更明确的 join syntax 和 ON
而不是 USING
.
的快捷方式
当使用 USING
子句连接时,输出中只有一个(必须相同的)连接列的实例 table,因此我们不需要 table 限定SELECT
列表(即使无论如何都会被允许)。
同时假设 student_grades.grade
是 character data type。否则您需要显式转换以获得 COALESCE
中的兼容数据类型。喜欢:COALESCE(g.grade::text, 'fail')
我有一个 table,其中包含学生在某些科目中的成绩。
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+
我还有另一个 table 包含主题列表。
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
和 his/her 年级的每个学生。如果STUDENT_GRADES
中某科目没有学生成绩,则该学生该科目成绩应为不及格。
使用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
您很可能还有另一个 table 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
(
假设 subjects
没有名为 student_id
的列并且 students
没有名为 subject_id
的列。否则你必须使用更明确的 join syntax 和 ON
而不是 USING
.
当使用 USING
子句连接时,输出中只有一个(必须相同的)连接列的实例 table,因此我们不需要 table 限定SELECT
列表(即使无论如何都会被允许)。
同时假设 student_grades.grade
是 character data type。否则您需要显式转换以获得 COALESCE
中的兼容数据类型。喜欢:COALESCE(g.grade::text, 'fail')