对sql ex-ru第57号的答复

对sql ex-ru第57号的答复,sql,Sql,嗨,我正试图解决这个问题: 对于有无法弥补的战斗损失且数据库中至少有三艘舰船的等级,显示该等级的名称和沉没的舰船数量 基于此数据库: 参加第二次世界大战的海军舰艇数据库正在考虑之中。数据库由以下关系组成: 等级(等级、类型、国家、数量、孔径、位移) 船舶(名称、等级、下水) 战斗(姓名、日期) 结果(船、战斗、结果) 不同级别的船舶都有相同的总体设计。类通常被指定为根据相应设计建造的第一艘船舶的名称,或与数据库中的任何船舶名称不同的名称。将其名称指定给某个类别的船舶称为领航船舶。 “类别”关系包

嗨,我正试图解决这个问题:

对于有无法弥补的战斗损失且数据库中至少有三艘舰船的等级,显示该等级的名称和沉没的舰船数量

基于此数据库: 参加第二次世界大战的海军舰艇数据库正在考虑之中。数据库由以下关系组成: 等级(等级、类型、国家、数量、孔径、位移) 船舶(名称、等级、下水) 战斗(姓名、日期) 结果(船、战斗、结果) 不同级别的船舶都有相同的总体设计。类通常被指定为根据相应设计建造的第一艘船舶的名称,或与数据库中的任何船舶名称不同的名称。将其名称指定给某个类别的船舶称为领航船舶。 “类别”关系包括类别名称、类型(战舰可以是bb,战舰可以是bc)、船建造国、主炮数量、炮口径(口径以英寸为单位)和排水量(重量以吨为单位)。Ships关系保存有关船舶名称、其相应类别的名称以及船舶下水年份的信息。战斗关系包含船只参与的战斗的名称和日期,以及结果关系-给定船只的战斗结果(可能是沉没、损坏或OK,最后一个值表示船只在战斗中安然无恙)。 注:1)结果关系可能包含ships关系中不存在的ships。2) 沉船不能参加以后的战斗。3) 由于历史原因,在许多练习中,主力舰被称为主力舰。4)在结果表中找到但未在舰船表中找到的舰船仍被视为数据库中的舰船。即使它沉没了,这也是事实

这是我提交的答案,它确实生成了正确的结果,但它说“您的查询在主数据库上生成了正确的结果集,但在第二个数据库上测试失败,即检查数据库 *错误的记录数(减少1)”:

我真的不知道我哪里出错了://

我想我明白了

当您的查询从T_Ships.C_Ships中带来可能不在T_Ships.C_Ships中的信息时,使用内部联接可能会带来T_Ships和T_类中都存在但不在T_结果中的信息。你的主表应该是T_结果,因为它应该有所有C_飞船。然而,你会有非机密船只。也许:

选择COALESCE(TC.C_类,“无_类”)作为类,计数(*)作为shipsunk
从T_结果到
左连接T0.C_船舶上的T_船舶=T.C_船舶
左连接T_类TS.C_类上的TC=TC.C_类
其中C_结果=‘沉没’
按合并分组(TC.C_类,“无_类”)

计数(*)大于等于3

For classes having irreparable combat losses and at least three ships in the database, display the name of the class and the number of ships sunk.
  • 对于有无法弥补的战斗损失的职业
这意味着该类至少应该有一艘沉船,要得到它,您将需要以下查询

  SELECT C.class, S.name, O.result FROM classes as C
  LEFT JOIN ships as S ON (C.class = S.class)
  LEFT JOIN outcomes as O ON (O.ship = S.name)
  WHERE O.result = 'sunk'
  UNION
  SELECT C.class, O.ship, O.result FROM classes as C
  LEFT JOIN outcomes as O ON (O.ship = C.class)
  WHERE O.result = 'sunk'
第一个查询将类与船舶连接起来,并过滤船舶以仅获取沉没的船舶

第二个查询获取未包含在ship表中的lead ships,并过滤这些ships以仅获取沉没的ships

稍后,我们需要将船只按类别分组并计数

WITH sunk_ships AS (
  SELECT C.class, S.name, O.result FROM classes as C
  LEFT JOIN ships as S ON (C.class = S.class)
  LEFT JOIN outcomes as O ON (O.ship = S.name)
  WHERE O.result = 'sunk'
  UNION
  SELECT C.class, O.ship, O.result FROM classes as C
  LEFT JOIN outcomes as O ON (O.ship = C.class)
  WHERE O.result = 'sunk'
),
clasess_with_sunk_ships AS (
 SELECT sships.class, COUNT(sships.result) sunk_count FROM sunk_ships sships
 GROUP BY sships.class
)
SELECT * FROM clasess_with_sunk_ships
  • 数据库中至少有三个ship的类
首先我们需要一份所有船只的清单

 SELECT C.class, S.name FROM classes as C
 JOIN ships as S ON (C.class = S.class)
 UNION
 SELECT C.class, O.ship FROM classes as C
 JOIN outcomes O ON (O.ship = C.class)
第一个查询将这些类与ships表连接起来

第二个查询获取未包含在ship表中的lead ships

有了这个列表,我们需要按类对船舶进行分组,并用至少3艘船舶过滤这些类

all_ships AS (
 SELECT C.class, S.name FROM classes as C
 JOIN ships as S ON (C.class = S.class)
 UNION
 SELECT C.class, O.ship FROM classes as C
 JOIN outcomes O ON (O.ship = C.class)
),
classes_with_valid_count AS (
 SELECT aships.class, COUNT(aships.name) count FROM all_ships as aships
 GROUP BY aships.class
 HAVING COUNT(aships.name) >= 3
)
SELECT * FROM classes_with_valid_count
clases\u与沉没船舶
classes\u与有效计数
的结合将给我们正确的答案

WITH sunk_ships AS (
  SELECT C.class, S.name, O.result FROM classes as C
  LEFT JOIN ships as S ON (C.class = S.class)
  LEFT JOIN outcomes as O ON (O.ship = S.name)
  WHERE O.result = 'sunk'
  UNION
  SELECT C.class, O.ship, O.result FROM classes as C
  LEFT JOIN outcomes as O ON (O.ship = C.class)
  WHERE O.result = 'sunk'
),
clasess_with_sunk_ships AS (
 SELECT sships.class, COUNT(sships.result) sunk_count FROM sunk_ships sships
 GROUP BY sships.class
),
all_ships AS (
 SELECT C.class, S.name FROM classes as C
 JOIN ships as S ON (C.class = S.class)
 UNION
 SELECT C.class, O.ship FROM classes as C
 JOIN outcomes O ON (O.ship = C.class)
),
classes_with_valid_count AS (
 SELECT aships.class, COUNT(aships.name) count FROM all_ships as aships
 GROUP BY aships.class
 HAVING COUNT(aships.name) >= 3
)
SELECT cwsships.class, cwsships.sunk_count FROM clasess_with_sunk_ships cwsships
JOIN classes_with_valid_count cwvcount ON (cwvcount.class = cwsships.class)


旁注:在
中用于
的子查询上使用
DISTINCT
在最好的情况下是没有意义的,在最坏的情况下,可能会诱使优化器做更多不必要的工作。(X,Y,Z,Y)
中的
a和(X,Y,Z)
中的
a的答案是相同的,因为
中的
是基于设置的-重复项不重要。无需选择DISTINCT,因为您的GROUP BY不会返回重复项。
WITH sunk_ships AS (
  SELECT C.class, S.name, O.result FROM classes as C
  LEFT JOIN ships as S ON (C.class = S.class)
  LEFT JOIN outcomes as O ON (O.ship = S.name)
  WHERE O.result = 'sunk'
  UNION
  SELECT C.class, O.ship, O.result FROM classes as C
  LEFT JOIN outcomes as O ON (O.ship = C.class)
  WHERE O.result = 'sunk'
),
clasess_with_sunk_ships AS (
 SELECT sships.class, COUNT(sships.result) sunk_count FROM sunk_ships sships
 GROUP BY sships.class
),
all_ships AS (
 SELECT C.class, S.name FROM classes as C
 JOIN ships as S ON (C.class = S.class)
 UNION
 SELECT C.class, O.ship FROM classes as C
 JOIN outcomes O ON (O.ship = C.class)
),
classes_with_valid_count AS (
 SELECT aships.class, COUNT(aships.name) count FROM all_ships as aships
 GROUP BY aships.class
 HAVING COUNT(aships.name) >= 3
)
SELECT cwsships.class, cwsships.sunk_count FROM clasess_with_sunk_ships cwsships
JOIN classes_with_valid_count cwvcount ON (cwvcount.class = cwsships.class)