我的查询有问题,我不知道这是什么吗?

时间:2019-10-12 19:12:15

标签: sql oracle

这是问题陈述:找到在战斗中失去所有船只的国家。

数据库描述为: enter image description here 简短的数据库描述“船舶”

正在考虑参加第二次世界大战的海军舰船数据库。该数据库包含以下关系:

Classes(class, type, country, numGuns, bore, displacement)
Ships(name, class, launched)
Battles(name, date)
Outcomes(ship, battle, result)

班级中的所有船舶都具有相同的总体设计。通常为类分配根据相应设计建造的第一艘船的名称,或与数据库中任何船名不同的名称。将其名称指定给某类的船称为领队。

“类别”关系包括类别名称,类型(战斗舰可以是bb,战斗巡洋舰可以是bc),舰艇的制造国家,主炮数量,枪口径(口径)英寸)和位移(重量以吨为单位)。

“船舶”关系保存有关船舶名称,其相应类别的名称以及船舶下水年份的信息。

“战斗”关系包含舰船参加的战斗的名称和日期。

结果关系-给定船的战斗结果(可能是沉没,损坏或确定,最后一个值表示该船在不受伤害的情况下幸存下来)。

注意:

  1. “结果”关系可能包含“船舶”关系中不存在的船舶。

  2. 沉没的船无法参加以后的战斗。

  3. 出于历史原因,在许多演习中,牵强舰被称为总舰。

  4. 在数据库中仍然考虑在“结果”表中找到但在“船”表中找不到的船。即使沉没也是如此。

这是我的代码:

select country
from Classes left join Ships
on classes.class=ships.class
right join Outcomes
on Classes.class=ship
or ships.name=ship
where ship in (select ship from outcomes where result = 'sunk') 
group by country
;

我的结局是日本德国,而无效的结局应该只是德国

3 个答案:

答案 0 :(得分:1)

似乎诀窍是在您的原始查询中添加and not exists (select 0 from ships where name = o.ship),不包括“船舶”表中不存在的船舶,当然“国家/地区”列的值不应为null,因为会询问相关国家/地区。因此,请考虑使用:

select country
  from Classes c
  left join Ships s
    on c.class = s.class 
 right join Outcomes o
    on c.class = ship
   and not exists (select 0 from ships where name = o.ship)
   and o.result = 'sunk'
 where c.country is not null
 group by country;

btw,使用ship in (select ship from outcomes where result = 'sunk')是多余的,and o.result = 'sunk'就足够了。

答案 1 :(得分:0)

我会使用having子句:

select c.country
from classes c join
     Ships s
     on c.class = s.class left join
     outcomes o
     on o.ship = s.name
group by c.country
having count(distinct s.name) = count(distinct case when o.result = 'sunk' then s.name end);

答案 2 :(得分:0)

我将每个国家的船只与每个国家沉没的船只进行了比较,我对它们进行了过滤以仅显示两个表中数量相同的国家

WITH ALL_SHIPS AS (
 SELECT ship, country from outcomes o
 JOIN classes c ON (c.class = o.ship)
 UNION
 SELECT name, country FROM ships s
 JOIN classes c ON (c.class = s.class)
),
SHIPS_PER_COUNTRY AS (
 SELECT country, COUNT(ship) count FROM ALL_SHIPS
 GROUP BY country
),
SHIPS_SUNK AS (
 SELECT ship, result FROM outcomes
 WHERE result = 'sunk'
),
SHIPS_SUNKED_PER_COUNTRY AS (
 SELECT aships.country, COUNT(ssunk.result) count FROM ALL_SHIPS aships
 JOIN SHIPS_SUNK ssunk ON (ssunk.ship = aships.ship)
 GROUP BY aships.country
)
SELECT spc.country FROM SHIPS_PER_COUNTRY spc
JOIN SHIPS_SUNKED_PER_COUNTRY sspc ON (sspc.country = spc.country)
WHERE spc.count = sspc.count