使用EXISTS/IN等运算符重写Oracle查询:查找参与Kongo级战役的舰船
优化后的查询方案
先明确需求核心:找出所有参与过Kongo级舰船所参与战役的舰船名称,而非仅Kongo级舰船本身(之前的版本1、2逻辑存在偏差,仅返回了Kongo级舰船,未覆盖其他参与相同战役的舰船)。以下是符合要求的优雅实现:
方案1:使用IN运算符
通过子查询先获取Kongo级舰船参与的所有战役,再筛选出参与这些战役的所有舰船:
SELECT DISTINCT s.name FROM ships s JOIN consequences c ON s.name = c.ship WHERE c.battle IN ( SELECT c2.battle FROM consequences c2 JOIN ships s2 ON c2.ship = s2.name WHERE s2.class = 'Kongo' );
逻辑说明:
- 内层子查询:获取所有Kongo级舰船参与过的战役名称
- 外层查询:关联舰船与战役表,筛选出参与上述战役的所有舰船,用
DISTINCT避免重复(同一舰船可能参与多次战役)
方案2:使用EXISTS运算符
利用相关性子查询判断当前舰船是否参与了任意一个Kongo级舰船参与的战役:
SELECT DISTINCT s.name FROM ships s JOIN consequences c ON s.name = c.ship WHERE EXISTS ( SELECT 1 FROM consequences c2 JOIN ships s2 ON c2.ship = s2.name WHERE s2.class = 'Kongo' AND c2.battle = c.battle );
逻辑说明:
- 外层查询遍历每一艘参与战役的舰船
- 内层子查询检查该舰船参与的战役是否有Kongo级舰船也参与过,存在则保留该舰船记录
SELECT 1是EXISTS子查询的最优写法,无需返回实际数据,仅判断存在性
当前测试数据的返回结果
由于测试数据中,Kongo级舰船参与的战役(Midway Battle、Guadalcanal Campaign)没有其他舰船参与,返回结果仍为Kongo、Haruna,但逻辑已覆盖需求的完整场景。
内容的提问来源于stack exchange,提问作者crpgdr
相关产品推荐
相关产品推荐

