【问题标题】:SQL-EX.ru query problemset #32SQL-EX.ru 查询问题集 #32
【发布时间】:2014-02-03 13:55:59
【问题描述】:

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

架构

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

SQL 查询问题:

一艘船的特征之一是其主炮口径(mw)的二分之一立方。在小数点后 2 位以内,定义数据库中每个国家的船舶的 mw 平均值。

关于数据的网站注释

参与二战的海军舰艇数据库正在考虑中。数据库有以下关系: 类(类,类型,国家,numGuns,孔,位移) 船舶(名称、等级、发射) 战斗(名称,日期) 结果(船,战斗,结果) 班级中的船舶被安排到一个项目中。一个类通常被分配给所考虑的类中的第一艘船的名称(头船);否则,类名与数据库中的任何船名不一致。 等级关系包括等级名称、类型(bb 代表战舰,或 bc 代表战列巡洋舰)、建造国家、主炮数量、炮口径(炮管直径,以英寸为单位)和排量(重量,吨)。 Ships 关系包括船名、船级名和发射年份。战斗关系包括舰艇参加的战斗的名称和日期;而他们参与战斗的结果(沉没、受损或安然无恙 - OK)在结果关系中。 注: 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

英国 1687.50

美国 1897.78

我的问题: 鉴于它产生正确的结果,我的查询如何不正确?非常感谢。

【问题讨论】:

  • 也许在 sql-ex.ru 上询问会更有意义。
  • 绝对正确,但只有在提供正确答案的情况下才能访问论坛上的问题讨论。 :(

标签: sql tsql


【解决方案1】:
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

【讨论】:

  • 您能否解释一下您的查询,以便其他人能够理解这如何完全解决了 OP 的问题?
【解决方案2】:

练习本身有问题(IMO)。

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

还有一些问题:

  1. 有一个舰船等级 (Bismark) 出现在等级表中,但不在舰船表格中。显然,即使它不存在,您也必须考虑到这一点。有人可能会争论,如何将实际存在的船舶的平均值与实际不存在的船舶的假设平均值包括在内?

如果您考虑到这一点,您将通过第一个 DB 而不是第二个。为什么?因为第二个问题:

  1. 为了完全通过,您还必须考虑出现在“结果”表中的船只名称,并将它们加入到带有结果.名称 = 类.class 的类中。为什么?不知道。 Bismark 是结果中唯一的一艘船的“名称”,也是类中的一个类的“名称”。他们为什么要加入?谁知道。你应该怎么猜?嗯...我不知道。这毫无意义。

因此,这两个问题非常不合逻辑(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

【讨论】:

    【解决方案3】:
    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
    

    【讨论】:

      【解决方案4】:

      好吧,我已经进行了这个查询,它产生了正确的结果,但页面不接受。

      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

      我的想法是,你只能计算类中存在的类的正确答案(你有数字),所以在这种情况下,结果对我来说是无用的表(没有意义检索我们没有数据的船类for),因为您可以从船舶表中选择每个类别的船舶数量,并根据给定数据计算所有字段。像俾斯麦这样的主要类别是通过左连接解决的,无论如何这只是其给定类型的一艘船。 .

      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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-12-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多