【问题标题】:answer to sql ex ru number 57回答 sql ex ru 编号 57
【发布时间】:2018-06-01 05:21:24
【问题描述】:

您好,我正在尝试解决这个特定问题:

对于具有不可挽回的战斗损失且数据库中至少有三艘船的班级,显示班级的名称和沉没的船只数量。

基于此数据库: 参与二战的海军舰艇数据库正在考虑中。数据库由以下关系组成: 类(类,类型,国家,numGuns,孔,位移) 船舶(名称、等级、发射) 战斗(名称,日期) 结果(船,战斗,结果) 各类船舶都具有相同的总体设计。一个类通常被分配一个根据相应设计建造的第一艘船的名称,或者一个不同于数据库中任何船名的名称。其名称被分配到一个级别的船称为领导船。 Classes 关系包括类的名称、类型(可以是 bb 表示战舰,或 bc 表示战列巡洋舰)、舰艇建​​造的国家、主炮数量、火炮口径(口径以英寸为单位) , 和排量(重量,以吨为单位)。 Ships 关系包含有关船舶名称、相应类别的名称以及船舶下水年份的信息。 Battles 关系包含船只参与的战斗的名称和日期,而 Outcomes 关系 - 给定船只的战斗结果(可能是沉没、损坏或 OK,最后一个值表示船只在战斗中幸存下来并没有受到伤害)。 注意: 1) 结果关系可能包含船舶关系中不存在的船舶。 2)沉船无法参加后期战斗。 3) 由于历史原因,在许多练习中将领头船称为头船。4) 在 Outcomes 表中找到但不在 Ships 表中的船仍被考虑在数据库中。即使沉没也是如此。

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

SELECT DISTINCT C.class, count(result)
  FROM classes c JOIN ships s ON
  c.class = s.class left join outcomes o on
   o.ship = s.name
WHERE result='sunk' 
   and c.class IN (
            SELECT DISTINCT c.class
            FROM classes c JOIN ships s ON
            c.class = s.class left join outcomes o on o.ship = s.name
           GROUP BY c.class
           HAVING count(name)>=3)
           group by c.class
           HAVING count(result) is not NULL

我不确定我哪里出错了://

【问题讨论】:

  • 旁注:在用于IN 的子查询上使用DISTINCT 充其量是没有意义的,最坏的情况是,可能会诱使优化器做更多的工作而不是必要的工作. a IN (X, Y, Z, Y)a IN (X, Y, Z) 的答案是相同的,因为 IN 是基于设置的 - 重复无​​关紧要。
  • 无需执行 SELECT DISTINCT,因为您的 GROUP BY 不会返回重复项。

标签: sql


【解决方案1】:

我想我明白了。

由于您的查询会带来 T_Outcomes.C_Ships 中可能不存在于 T_Ships.C_Ships 中的信息,因此使用内连接可能会带来 T_Ships 和 T_Class 中存在但不存在于 T_Outcomes 中的信息。您的主表应该是 T_Outcomes,因为它应该包含所有 C_Ships。但是,您将拥有未分类的船只。也许:

SELECT COALESCE(TC.C_Class, 'No_Class') AS Class, COUNT(*) AS ShipsSunk FROM T_Outcomes T0 LEFT JOIN T_Ships TS ON T0.C_Ships = TS.C_Ships LEFT JOIN T_Classes TC on TS.C_Class = TC.C_Class WHERE C_Result = 'Sunk' GROUP BY COALESCE(TC.C_Class, 'No_Class') HAVING COUNT(*) >= 3;

【讨论】:

    【解决方案2】:

    根据问题描述

    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'
    

    第一个查询将类与船只连接起来,并过滤船只以仅获取沉没的船只。

    第二个查询获取未包含在船表中的主要船只,并过滤船只以仅获取沉没的船只。

    稍后我们需要按类别对船只进行分组并计数

    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
    
    • 数据库中至少包含三艘船的类别

    首先我们需要一份所有船只的清单

     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)
    

    第一个查询将类与 ship 表连接起来。

    第二个查询获取未包含在船舶表中的主要船舶

    有了这个列表,我们需要按类别对船进行分组,并过滤​​至少有 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
    

    clasess_with_sunk_shipsclasses_with_valid_count的加入会给我们正确的答案

    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)
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-14
      • 1970-01-01
      • 1970-01-01
      • 2016-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多