我正在尝试编写一个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
我的问题: 如果得出正确的结果,我的查询怎么不正确?非常感谢。
答案 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,并根据实际的船舶数量计算平均重量。
然而,有一些问题:
如果考虑到这一点,您将通过第一个数据库而不是第二个数据库。为什么?由于第二个问题:
所以,这两个问题是非常不合逻辑的(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
这是正确的答案,不同之处在于结果中可能有船舶不在船舶表中,即使它们不是。所以你必须考虑到这个