SQL-EX.ru查询问题集#32

时间:2014-02-03 13:56:00

标签: sql tsql

我正在尝试编写一个SQL查询来解决www.sql-ex.ru(问题32)中的问题,我得到了正确的结果,但网站验证我的查询是一个不受欢迎的解决方案。 (可能出于各种原因:逻辑错误或效率低下等......)

架构

http://www.sql-ex.ru/images/ships.gif

SQL查询问题:

  

船的一个特征是其主炮(mw)口径的一半立方体。在小数点后两位,定义每个国家的船舶在数据库中有船舶的平均值mw。

有关数据的网站说明

  

正在考虑参加第二次世界大战的海军舰艇数据库。该数据库具有以下关系:   类(类,类型,国家,numGuns,钻孔,位移)   船舶(名称,类别,已推出)   战斗(姓名,日期)   结果(船,战斗,结果)   课程中的船只安排在一个项目中。通常会为一类人员分配正在考虑的类别中的第一艘船的名称(船头);否则,类名与数据库中的任何船名不一致。   Classes关系包括班级名称,类型(战斗船的bb,战斗巡洋舰的bc),建造船舶的国家,主炮的数量,枪口径(枪管的直径,以英寸为单位),以及排量(重量以吨计)。船舶关系包括船名,船级名称和发射年份。战斗关系包括船舶参与战斗的名称和日期;而他们参与战斗的结果(沉没,受损或无伤害 - 好的)是在结果关系中。   注:1)结果关系可能包括未包含在船舶关系中的船舶。 2)沉船在此之后不能参加战斗。

我的查询

            SELECT c.country, CAST( AVG(0.5*POWER(c.bore,3.0) ) AS DECIMAL(10,2) )
            AS  weight FROM
    (
    SELECT ship FROM Outcomes
    INTERSECT
    SELECT class FROM Classes
    EXCEPT
    SELECT class FROM Ships
    UNION ALL
    SELECT class FROM Ships

    ) AS cte1

    LEFT OUTER JOIN Classes AS c
    ON cte1.ship=c.class
    GROUP BY country

正确结果

  

国家重量

     

德国1687.50

     

Gt.Britain 1687.50

     

美国1897.78

我的问题: 如果得出正确的结果,我的查询怎么不正确?非常感谢。

4 个答案:

答案 0 :(得分:3)

select country, convert(numeric(10, 2), avg(power(bore, 3)/2)) weight 
from
    (select country, bore, name from classes c, ships s
     where s.class=c.class
     union
     select country, bore, ship from classes c, outcomes o
     where o.ship=c.class 
     and o.ship not in(select distinct name from ships))x
group by country

答案 1 :(得分:2)

运动本身有缺陷(IMO)。

您要做的是根据他们的等级加入两个表,Classes和Ships,并根据实际的船舶数量计算平均重量。

然而,有一些问题:

  1. 有一个船级(Bismark)出现在类表中,但不出现在船只表中。显然你必须考虑到这一点,即使它不存在。有人可能会争辩说,你怎么能包括实际存在的平均船只以及实际上不存在的假想平均船舶?
  2. 如果考虑到这一点,您将通过第一个数据库而不是第二个数据库。为什么?由于第二个问题:

    1. 为了完全通过,您还必须考虑出现在Outcomes表中的船舶名称,并将它们与带有outcomes.names = classes.class的类连接起来。为什么?不知道。 Bismark是结果中船舶的唯一“名称”,也是类中类的“名称”。他们为什么要加入?谁知道。你怎么猜这个?嗯......我不知道。它没有任何意义。
    2. 所以,这两个问题是非常不合逻辑的(IMO),虽然第一个问题有点好,但第二个问题完全荒谬。

      例如,这解决了第一个数据库,但第二个数据库失败了:

      --t1, t1_2, t1_3 are creating a class table with count of no. of ships. Any ship appearing only in the classes table would be assigned a count of 1.
      with t1 as 
      (Select class, count(name) 'c1' from ships group by class),
      t1_2 as
      (select ship 'class', 1 'c1' from outcomes where ship not in (select class from t1)),
      t1_3 as
      (select * from t1 union select * from t1_2),
      
      t2 as
      (select distinct classes.class, country, 0.5*bore*bore*bore 'mw', c1 from classes left join t1_3 on t1_3.class = classes.class)
      select country, cast(sum(mw*c1)/sum(c1) as decimal(10,2)) from t2 group by country
      

      这完全解决了这个问题:

      with t1 as
      (select country, bore, name from classes, ships
      where classes.class=ships.class
      union
      select country, bore, ship 'name' from classes, outcomes
      where classes.class = outcomes.ship)
      select country, cast(avg(0.5*bore*bore*bore) as decimal(10,2)) 'mw' 
      from t1 group by country
      

答案 2 :(得分:0)

SELECT COUNTRY, CONVERT(NUMERIC(10,2),AVG(BORE*BORE*BORE/2)) WEIGHT 
FROM (SELECT COUNTRY,BORE,NAME
    FROM CLASSES 
    RIGHT JOIN SHIPS ON SHIPS.CLASS = CLASSES.CLASS
    UNION
    SELECT DISTINCT COUNTRY, BORE, SHIP
    FROM CLASSES C 
    LEFT JOIN OUTCOMES O ON O.SHIP = C.CLASS 
    WHERE  NOT EXISTS(SELECT NAME 
    FROM SHIPS 
    WHERE NAME = O.SHIP) AND 
    NOT (SHIP IS NULL)
 )T
GROUP BY COUNTRY

答案 3 :(得分:0)

好吧,我已经完成了这个查询并且它正确的结果,但页面不接受。

select c.country, convert(numeric(10, 2), avg(power(bore, 3)/2)) as weight from classes as c left join ships as s on (s.class = c.class) group by c.country

我的想法是你只能计算出类中存在的类(你有数字)的正确答案,所以在这种情况下我的结果是无用的表(没有点检索我们没有数据的船只类别因为你可以从船舶表中选择每个级别的船只数量,并从给定的数据中计算出所有的油田。并且像俾斯麦这样的主要类别由左连接解决,左连接只是其给定类型的一艘船。

select country, convert(numeric(10, 2), avg(power(bore, 3)/2)) as weight from classes inner join (SELECT Ships.name, Ships.class FROM Ships inner join Classes ON Ships.class = Classes.class union SELECT Outcomes.ship, Classes.class FROM Outcomes inner join Classes ON Outcomes.ship = Classes.class ) as ships on (ships.class = classes.class) group by country

这是正确的答案,不同之处在于结果中可能有船舶不在船舶表中,即使它们不是。所以你必须考虑到这个