很难为这一个写好标题......
我的postgresql数据库中有4个表:
courses:
| id | data | created_at | updated_at | status |
course_versions:
| id | course_id | data | created_at | updated_at | status |
course_progresses:
| id | course_version_id | user_id | data | created_at | updated_at |
users:
| id | email |
课程可以有多个course_versions,用户可以拥有course_progresses,每个course_progress都连接到course_version。现在,我想获取特定用户的所有course_versions,也就是说,如果用户没有{_ 1}}的course_version的course_progress,它应该返回最新的course_version。如果用户的course_version为course id: 1
的course_progress,则应返回course_version,无论是否有更新的course_versions ...获取它? :)
这是一个有效的查询:
course id: 2
虽然对我来说看起来很可怕......有没有更好的方法来编写这个查询?
答案 0 :(得分:0)
您可以使用cross join
创建用户和课程的2D矩阵。对于每个条目,请查找具有进度的版本或最新版本:
select u.email
, c.course_id
, coalesce(progress_version.created_at, latest_version.created_at)
from users u
cross join
courses c
left join
(
select cp.user_id
, cv.course_id
, cv.created_at
from course_progresses cp
join course_versions cv
on cv.id = cp.course_version_id
) progress_version
on progress_version.user_id = u.id
and progress_version.course_id = c.id
left join
(
select row_number() over (partition by course_id
order by created_at desc) rn
, *
from course_versions
) latest_version
on latest_version.course_id = c.id
and latest_version.rn = 1
答案 1 :(得分:0)
如果没有您的示例数据,很难写出来,但是:
with -- Example data, just to check that there are no syntax errors
courses(id, status) as (values
(1,1),(2,1),(3,0)),
course_versions(id, course_id, status, created_at) as (values
(1,1,1,current_timestamp),(2,1,1,current_timestamp),(3,2,1,current_timestamp),(4,2,0,current_timestamp)),
course_progresses(id, course_version_id, user_id) as (values
(2,3,123))
select distinct on (cp.course_version_id, cv.course_id)
cv.*
from
course_versions as cv
join courses as c on (c.id = cv.course_id and c.status = 1 and cv.status = 1)
left join course_progresses cp on (cp.course_version_id = cv.id and cp.user_id = 123)
order by
cp.course_version_id nulls last, cv.course_id, cv.created_at desc;