如何在PostgreSQL中更高效地编写多个EXISTS子查询
优化多子查询的工作流关联查询
我需要查询同时关联了两种特定任务类型的工作流,现有查询能得到正确结果,但用了多个EXISTS子查询,想改成更高效的单查询或用连接实现。
原查询代码:
SELECT * FROM workflow w WHERE EXISTS (SELECT ti.id FROM task_instance ti left join workflow_task_instance wti ON ti.id = wti.task_instance_id WHERE ti.task_type = 'TASK_ONE' AND wti.workflow_id = w.id) AND EXISTS (SELECT ti.id FROM task_instance ti left join workflow_task_instance wti ON ti.id = wti.task_instance_id WHERE ti.task_type = 'TASK_TWO' AND wti.workflow_id = w.id);
方案一:JOIN+GROUP BY+HAVING(单查询实现)
通过关联表筛选目标任务,按工作流分组后校验是否同时包含两种任务类型:
SELECT w.* FROM workflow w JOIN workflow_task_instance wti ON w.id = wti.workflow_id JOIN task_instance ti ON wti.task_instance_id = ti.id WHERE ti.task_type IN ('TASK_ONE', 'TASK_TWO') GROUP BY w.id, w.[其他工作流表字段] -- 需根据数据库规则,将SELECT中的非聚合字段加入GROUP BY HAVING COUNT(DISTINCT ti.task_type) = 2;
注:COUNT(DISTINCT)用于避免同一任务类型重复计数导致的误判,如果单个工作流不会关联多个同类型任务,也可以简化为COUNT(*) = 2,但前者兼容性和严谨性更强。
方案二:IN子查询(单嵌套子查询)
先在子查询中筛选出符合条件的工作流ID,再关联主表获取详情:
SELECT * FROM workflow w WHERE w.id IN ( SELECT wti.workflow_id FROM workflow_task_instance wti JOIN task_instance ti ON wti.task_instance_id = ti.id WHERE ti.task_type IN ('TASK_ONE', 'TASK_TWO') GROUP BY wti.workflow_id HAVING COUNT(DISTINCT ti.task_type) = 2 );
注:这种方式将筛选逻辑集中在子查询,主表只需匹配已过滤的ID,减少主查询的计算量。
方案三:多JOIN替代EXISTS(无嵌套子查询)
通过两次关联分别匹配两种任务类型,最后去重得到结果:
SELECT DISTINCT w.* FROM workflow w JOIN workflow_task_instance wti1 ON w.id = wti1.workflow_id JOIN task_instance ti1 ON wti1.task_instance_id = ti1.id AND ti1.task_type = 'TASK_ONE' JOIN workflow_task_instance wti2 ON w.id = wti2.workflow_id JOIN task_instance ti2 ON wti2.task_instance_id = ti2.id AND ti2.task_type = 'TASK_TWO';
注:DISTINCT用于去除因同一工作流关联多个同类型任务产生的重复行。
内容的提问来源于stack exchange,提问作者Nelaina
相关产品推荐
相关产品推荐

