sql - 根据是否存在另一个表行来选择行
问题描述
很难为这个写一个好标题...
我的 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_version,一个用户可以有 course_progresses,每个 course_progress 都连接到一个 course_version。现在,我想获取特定用户的所有 course_versions,也就是说,如果用户没有 course_version 的 course_progress,course id: 1
它应该返回最新的 course_version。如果用户有 course_progress 的course id: 2
course_version 则应该返回该 course_version,无论是否有较新的 course_versions... 明白吗?:)
这是一个有效的查询:
WITH
course_versions_with_progress AS (
SELECT cv.*
FROM course_versions AS cv
INNER JOIN courses AS c ON c.id = cv.course_id
INNER JOIN course_progresses AS cp ON cp.course_version_id = cv.id
WHERE c.status = 1 AND cv.status = 1 AND cp.user_id = 123
),
latest_course_versions AS (
SELECT DISTINCT ON(cv.course_id) cv.*
FROM course_versions AS cv
INNER JOIN courses AS c ON c.id = cv.course_id
WHERE c.status = 1 AND cv.status = 1
ORDER BY cv.course_id, cv.created_at DESC
)
SELECT * FROM course_versions_with_progress
UNION
SELECT * FROM latest_course_versions
WHERE NOT EXISTS (
SELECT 1
FROM course_versions_with_progress
WHERE course_id = latest_course_versions.course_id
)
不过,这对我来说看起来很可怕……有没有更好的方法来编写这个查询?
解决方案
您可以使用 across join
创建用户和课程的二维矩阵。对于每个条目,查找具有进度的版本或最新版本:
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
推荐阅读
- javascript - 在 iFrame 中滚动的 WebRTC
- python-3.x - Python 中的 Reddit 和 Twitter bot 使用 PRAW
- javascript - 如何在导出默认值中调用函数内部的另一个函数?
- spring-boot - SunCertPathBuilderException:无法找到请求目标的有效认证路径,但问题不同
- java - 如何在android studio中用户输入时从sharedPreferences中删除某些字符串
- python - python sounddevice - 如何播放我同时录制的一段音频?
- c# - 如何从 ASP.NET Core 表单中获取嵌套字段?
- reactjs - 浏览器前进按钮在 React.js 中无效
- mysql - 异步等待递归在 MySQL 查询完成之前过早执行
- python - 如何按列值在 Pandas 中创建单独的行?