PostgreSQL多对多表查询:判断指定运动员是否加入班级
解决PostgreSQL中查询每个班级是否包含指定运动员的问题
嘿,我明白你的问题啦!你现在的SQL语句是直接从classes_athletes表逐条查询,所以会返回每一条报名记录的判断结果,而不是每个班级只返回一行。咱们需要调整思路,先拿到所有班级的ID,再逐个判断指定运动员是否报名了这个班级。
这里有两种靠谱的方法可以实现你的需求:
方法一:使用LEFT JOIN + 聚合函数
这个方法先从classes表获取所有班级(确保哪怕没有运动员报名的班级也能被查到),然后左连接classes_athletes表并过滤指定的运动员ID,最后通过聚合函数判断该班级是否存在这个运动员的报名记录:
SELECT c.class_id, CAST(MAX(CASE WHEN ca.athlete_id = 1 THEN 1 ELSE 0 END) AS bit) AS athleteIsEnrolled FROM classes c LEFT JOIN classes_athletes ca ON c.class_id = ca.class_id AND ca.athlete_id = 1 GROUP BY c.class_id;
原理说明:
LEFT JOIN会保留所有班级,不管该班级有没有指定运动员的报名记录- 当存在指定运动员的报名时,
CASE语句返回1,否则返回0 MAX()聚合函数会取出每个班级的最大值,只要有一条匹配记录,结果就是1,否则是0- 最后转成
bit类型符合你需要的输出格式
方法二:使用EXISTS子查询
这种方法更直观,直接检查每个班级是否存在指定运动员的报名记录,代码更简洁:
SELECT c.class_id, CAST(EXISTS ( SELECT 1 FROM classes_athletes ca WHERE ca.class_id = c.class_id AND ca.athlete_id = 1 ) AS bit) AS athleteIsEnrolled FROM classes c;
原理说明:
EXISTS子查询会判断当前班级是否存在指定运动员的报名记录,返回布尔值true或false- 把布尔值转成
bit类型后,true会变成1,false变成0,正好是你需要的结果 - 不需要分组查询,执行效率也很高
这两种方法都能满足你的需求:当指定athlete_id=1时,两个班级都返回1;指定athlete_id=99时,都返回0。
如果你的classes表中没有所有班级的记录(比如有些班级只在classes_athletes里存在),可以把FROM classes c改成FROM (SELECT DISTINCT class_id FROM classes_athletes) c,这样就能覆盖所有有报名记录的班级啦。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

