如何用SQL实现战舰受损次数统计(无受损显示0)及受损后获胜战舰查询
问题1:无受损记录的战舰缺失的SQL调整
原SQL核心错误
- 过滤条件位置错误:原语句将
result = 'damaged'放在WHERE子句中,会让LEFT JOIN退化为内连接——所有非damaged结果的记录都会被WHERE条件直接筛除,从未有过受损战斗的战舰自然不会出现在最终结果中。 - 统计逻辑偏差:原语句的
COUNT没有针对damaged记录做定向统计,无法对无受损记录的战舰返回0值。
调整后的SQL
SELECT Outcomes.Ship, COUNT(CASE WHEN Outcomes.result = 'damaged' THEN 1 END) AS NumberOfDamagedBattles FROM outcomes LEFT JOIN Battles ON Outcomes.battle = Battles.name GROUP BY Ship;
调整说明
- 移除原WHERE子句中的damaged过滤条件,保证所有参战战舰(即outcomes表中出现的所有战舰)都会被分组保留。
- 用
CASE判断将damaged的统计逻辑内置到COUNT中:只有result为damaged的记录会被计数,其余记录不参与统计,无受损记录的战舰统计值自然为0。 - 去掉冗余的
LIKE写法,无通配符匹配时直接用等值判断更高效。
问题2:查询先受损、后获胜的战舰
实现逻辑
通过两次关联outcomes表,分别匹配同一艘战舰的受损战斗、获胜战斗记录,再关联battles表的日期字段,对比两场战斗的先后顺序,筛出满足“获胜战斗日期晚于受损战斗日期”的战舰,最后去重返回结果。
对应SQL
SELECT DISTINCT damaged_records.ship FROM outcomes AS damaged_records -- 关联受损战斗的日期字段 JOIN battles AS damaged_battle ON damaged_records.battle = damaged_battle.name -- 关联同战舰的获胜战斗记录 JOIN outcomes AS win_records ON damaged_records.ship = win_records.ship AND win_records.result = 'win' -- 关联获胜战斗的日期字段 JOIN battles AS win_battle ON win_records.battle = win_battle.name -- 筛选核心条件 WHERE damaged_records.result = 'damaged' AND win_battle.date > damaged_battle.date;
逻辑说明
- 用
DISTINCT去重,避免同一艘船存在多组“受损-后续获胜”关联时,结果集中重复出现同一战舰名。 - 严格通过战斗日期对比保证先后顺序:只认日期更晚的获胜战斗,不满足时间顺序的记录会被自动过滤。
内容的提问来源于stack exchange,提问作者M8 Dim
相关产品推荐
相关产品推荐

