多子表SQL条件查询:父表关联9个平行子表判断是否存在草稿
实现方案
当然可行!针对你的场景,我整理了两种实用的实现思路,既能解决Version列的歧义问题,又能准确生成你需要的HasDrafts字段:
方法一:使用EXISTS子查询(推荐)
这种方式性能更优,尤其是子表数据量较大的时候,因为EXISTS只做存在性判断,找到匹配记录就会停止查询,不会遍历全表。核心是给每个子表加别名,明确指定Version列的来源,避免歧义:
SELECT p.*, CASE WHEN EXISTS (SELECT 1 FROM child1 c1 WHERE c1.parent_id = p.id AND c1.Version = 0) OR EXISTS (SELECT 1 FROM child2 c2 WHERE c2.parent_id = p.id AND c2.Version = 0) OR EXISTS (SELECT 1 FROM child3 c3 WHERE c3.parent_id = p.id AND c3.Version = 0) OR EXISTS (SELECT 1 FROM child4 c4 WHERE c4.parent_id = p.id AND c4.Version = 0) OR EXISTS (SELECT 1 FROM child5 c5 WHERE c5.parent_id = p.id AND c5.Version = 0) OR EXISTS (SELECT 1 FROM child6 c6 WHERE c6.parent_id = p.id AND c6.Version = 0) OR EXISTS (SELECT 1 FROM child7 c7 WHERE c7.parent_id = p.id AND c7.Version = 0) OR EXISTS (SELECT 1 FROM child8 c8 WHERE c8.parent_id = p.id AND c8.Version = 0) OR EXISTS (SELECT 1 FROM child9 c9 WHERE c9.parent_id = p.id AND c9.Version = 0) THEN 1 -- 可以替换为 TRUE / '是' 等你需要的标识值 ELSE 0 -- 可以替换为 FALSE / '否' 等你需要的标识值 END AS HasDrafts FROM parent_table p;
说明:
- 把
parent_id替换成你实际的父表与子表的关联字段; - 每个子表都用了独立的别名(
c1到c9),引用Version列时加上别名前缀(c1.Version),彻底解决歧义问题; - HasDrafts的取值可以根据业务需求调整,比如用布尔值或字符串。
方法二:LEFT JOIN + 聚合函数
如果你更习惯用JOIN的方式,也可以通过LEFT JOIN关联所有子表,再用聚合函数判断是否存在草稿:
SELECT p.*, CASE WHEN MAX( CASE WHEN c1.Version = 0 THEN 1 WHEN c2.Version = 0 THEN 1 WHEN c3.Version = 0 THEN 1 WHEN c4.Version = 0 THEN 1 WHEN c5.Version = 0 THEN 1 WHEN c6.Version = 0 THEN 1 WHEN c7.Version = 0 THEN 1 WHEN c8.Version = 0 THEN 1 WHEN c9.Version = 0 THEN 1 ELSE 0 END ) = 1 THEN 1 ELSE 0 END AS HasDrafts FROM parent_table p LEFT JOIN child1 c1 ON c1.parent_id = p.id LEFT JOIN child2 c2 ON c2.parent_id = p.id LEFT JOIN child3 c3 ON c3.parent_id = p.id LEFT JOIN child4 c4 ON c4.parent_id = p.id LEFT JOIN child5 c5 ON c5.parent_id = p.id LEFT JOIN child6 c6 ON c6.parent_id = p.id LEFT JOIN child7 c7 ON c7.parent_id = p.id LEFT JOIN child8 c8 ON c8.parent_id = p.id LEFT JOIN child9 c9 ON c9.parent_id = p.id GROUP BY p.id, p.col1, p.col2, ... -- 列出父表所有列,部分数据库支持简化为 GROUP BY p.*
说明:
- LEFT JOIN确保父表的所有记录都会被保留,即使没有对应的子表记录;
- 内层CASE判断每个子表是否存在草稿,外层MAX函数只要有一个子表存在草稿就会返回1;
- GROUP BY用于去重,避免因为子表有多条关联记录导致父表记录重复。
关键注意点
- 解决Version歧义的核心:永远给子表加别名,引用Version列时必须带上别名前缀(比如
c1.Version),不要直接写Version; - 性能对比:EXISTS子查询通常比LEFT JOIN+GROUP BY更快,尤其是子表数据量大的场景,建议优先选择方法一;
- 灵活调整:HasDrafts的取值可以根据业务需求修改,比如用
'Yes'/'No'或者布尔类型(TRUE/FALSE)。
内容的提问来源于stack exchange,提问作者J Santosh
相关产品推荐
相关产品推荐

