基于唯一ID遍历表,查询学员未完成培训记录的SQL需求
解决方案
核心思路
要找出所有学员未完成的培训,首先需要生成所有学员与所有培训的全量组合(即每个学员理论上需要完成的所有培训),再从中排除已经完成(result=1)的记录,剩下的就是未完成的培训(包括从未参加的培训、参加但未通过的培训)。
形式1:输出nameid和typeid
可以用NOT EXISTS子查询直接排除已完成的记录:
SELECT n.nameid, t.typeid FROM names n CROSS JOIN training t WHERE NOT EXISTS ( SELECT 1 FROM log l WHERE l.nameid = n.nameid AND l.typeid = t.typeid AND l.result = 1 ) ORDER BY n.nameid, t.typeid;
也可以用LEFT JOIN实现逻辑等价的查询:
SELECT n.nameid, t.typeid FROM names n CROSS JOIN training t LEFT JOIN log l ON l.nameid = n.nameid AND l.typeid = t.typeid AND l.result = 1 WHERE l.nameid IS NULL ORDER BY n.nameid, t.typeid;
形式2:输出学员姓名与培训类型名称
只需在上述查询基础上,直接关联表中的名称字段即可:
SELECT n.name, t.training_name FROM names n CROSS JOIN training t WHERE NOT EXISTS ( SELECT 1 FROM log l WHERE l.nameid = n.nameid AND l.typeid = t.typeid AND l.result = 1 ) ORDER BY n.name, t.training_name;
关键说明
CROSS JOIN的作用是生成学员与培训的全量组合,确保不会遗漏任何学员需要完成的培训项。- 如果
log表中存在同一学员同一培训的多条记录,只要有一条result=1,就会被视为已完成并排除。 - 若业务中需要区分“未参加”和“已参加未通过”,可以扩展查询显示状态:
SELECT n.name, t.training_name, CASE WHEN l.result = 0 THEN '已参加未通过' ELSE '未参加' END AS status FROM names n CROSS JOIN training t LEFT JOIN log l ON l.nameid = n.nameid AND l.typeid = t.typeid WHERE l.result IS NULL OR l.result = 0 ORDER BY n.name, t.training_name;
内容的提问来源于stack exchange,提问作者user27280979
相关产品推荐
相关产品推荐

