SQL多表查询:如何判断每个行程是否包含活动日
多表关联去重及行程活动状态判断方案
问题背景
现有三张表:
- USERS表:
id_user(用户ID)、name(用户名) - TRAVEL表:
id_travel(行程ID)、id_user(关联用户ID) - TRAVEL_DAYS表:
id_tdays(日期ID)、id_travel(关联行程ID)、day_has_activities(当日是否有活动)
执行原关联查询时,因单一行程对应多个日期,结果出现重复行:
SELECT t.id_travel, u.name, td.day_has_activities FROM travel t left join users u on u.id_user = t.id_user left join travel_days td on td.id_travel = t.id_travel
使用DISTINCT无法解决问题,因为day_has_activities仅代表单日期状态,无法覆盖整个行程。需求为每个行程仅返回一条记录,新增travel_has_activities字段,判断该行程是否存在任意一日有活动(存在返回yes,否则返回no)。
错误SQL问题分析
你尝试的SQL无法执行,核心问题:
- 子查询中
from t错误引用主查询的TRAVEL表,实际应查询TRAVEL_DAYS表 - 子查询未添加与主行程的关联条件,逻辑不成立
- 即使修正子查询,未处理多日期导致的重复行问题
正确实现方案
方案一:先聚合行程日期数据再关联
先对TRAVEL_DAYS按行程分组,提前判断该行程是否有活动日期,再与其他表关联,从根源避免重复行:
SELECT t.id_travel, u.name, CASE WHEN td.has_activity = 1 THEN 'yes' ELSE 'no' END AS travel_has_activities FROM travel t LEFT JOIN users u ON u.id_user = t.id_user LEFT JOIN ( -- 按行程分组,标记是否存在有活动的日期 SELECT id_travel, MAX(CASE WHEN day_has_activities = 'yes' THEN 1 ELSE 0 END) AS has_activity FROM travel_days GROUP BY id_travel ) td ON td.id_travel = t.id_travel
方案二:使用EXISTS子查询直接判断
通过EXISTS子查询直接检查当前行程是否存在有活动的日期,无需分组,查询性能更高效(找到符合条件的记录即停止遍历):
SELECT t.id_travel, u.name, CASE WHEN EXISTS ( SELECT 1 FROM travel_days td WHERE td.id_travel = t.id_travel AND td.day_has_activities = 'yes' ) THEN 'yes' ELSE 'no' END AS travel_has_activities FROM travel t LEFT JOIN users u ON u.id_user = t.id_user
说明
两种方案均能保证每个行程仅返回一条记录,且准确判断行程是否存在活动日期。方案二更适合数据量较大的场景,因为EXISTS的查询逻辑更轻量化。
内容的提问来源于stack exchange,提问作者EMP
相关产品推荐
相关产品推荐

