I have a PostgreSQL database with three tables:
user: A list of users of the application. Primary key isuser_id.course: A catalog of courses that users can enroll into. Primary key iscourse_id.enrollment: Records of the users' enrollment into courses. Primary key isenrollment_id.
Relations between the tables:
The
enrollmenttable has two foreign keys that can not be null:enrollment.user_idreferencesuser.user_id.enrollment.course_idreferencescourse.course_id.
If
user1is enrolled incourse1, there should be only one record in theenrollmenttable that can be used to joinuser1tocourse1.If
user1is not enrolled incourse1, no record exists in theenrollmenttable to joinuser1tocourse1.
The problem:
- I can not find out how to write a database view which, if I have 2 users and 3 courses, returns 6 rows that look like this:
user_id | course_id | enrollment_id
-------------------------------------
user1 | course1 | enrollment id of user1 for course1 or null
user1 | course2 | enrollment id of user1 for course2 or null
user1 | course3 | enrollment id of user1 for course3 or null
user2 | course1 | enrollment id of user2 for course1 or null
user2 | course2 | enrollment id of user2 for course2 or null
user2 | course3 | enrollment id of user2 for course3 or null
Some context:
- I can not change anything about the database.
- I am not concerned about performance.
My work in progress:
I candidly hoped that this would work:
select user.user_id, course.course_id, enrollment.enrollment_id
from user
full outer join enrollment on enrollment.user_id = user.user_id
full outer join course on course.course_id = enrollment.course_id
This query does not return the results I'm expecting due to the fact that there isn't an enrollment record for courses the users are not enrolled into. The results, for example, look more like this:
user_id | course_id | enrollment_id
-------------------------------------
user1 | null | null
user2 | course1 | enrollment id of user2 for course1
user2 | course2 | enrollment id of user2 for course2
Which is not what I expect, as I wish the table to return 3 records for user1, who is not enrolled in any course, instead of only one row where course_id and enrollment_id are null. Similarly, a third record for user2 is missing since they are not enrolled in course3, which is not what I'm hoping for.
How can I solve this problem?
cross join users & courses, left join enrollment:
dbfiddle here (Postgres 14)