Трудно что-то написать без примеров данных от вас, но:
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;