我正在关注http://www.sql-ex.ru/learn_exercises.php中的练习。
在练习51中,他们要求“在具有相同位移的所有船舶中查找具有最多枪支的船舶的名称(包括在结果表中的船舶)。”
这是我的代码,它通过了第一个看到的数据库,但没有通过第二个,看不见的数据库(错误是 - “少于3”):
with t1 as
(select displacement, max(numguns) 'guns' from classes group by displacement),
t2 as
(select class from classes, t1 where classes.displacement = t1.displacement and classes.numguns = t1.guns)
select name from ships, t2 where ships.class = t2.class
union
select ship from outcomes, t2 where outcomes.ship = t2.class
我使用的逻辑是db中持有位移和枪支数量的唯一表是Classes,因此t1和t2提取类名,然后我只从船上获取属于这些类的名称结果表。
无法理解为什么会出现任何错误。
编辑:在类中添加了对空值的检查,并且在第二个看不见的数据库上出现了新错误 - “数据不匹配(11)”:
with t1 as
(select displacement, max(numguns) 'guns' from classes group by displacement),
t2 as
(select class from classes, t1 where (classes.displacement = t1.displacement or classes.displacement is null) and (classes.numguns = t1.guns or classes.numguns is null))
select name from ships, t2 where ships.class = t2.class
union
select ship from outcomes, t2 where outcomes.ship = t2.class
答案 0 :(得分:1)
如果您将查看相关练习的数据库描述,您将看到:
班级中的船舶都具有相同的总体设计。通常是类 根据,分配了第一艘建造的船的名称 相应的设计,或与任何船名不同的名称 在数据库中。 调用名称分配给类的船 领先船。
这意味着outcomes
表可能包含潜水客船,其名称在表classes
中用作类。这就是为什么union
需要ship
来自outcomes
的{{1}}名称和类,因为lead ship
与名称相同。
所以,你可以使用这个查询或类似的逻辑:
WITH cte
AS ( SELECT A.name ,
C.numGuns ,
C.displacement
FROM ( SELECT S.name ,
S.class
FROM dbo.Ships AS S
UNION
SELECT O.ship ,
O.ship
FROM dbo.Outcomes AS O
) AS A
JOIN dbo.Classes AS C ON A.class = C.class
)
SELECT cte.name
FROM cte
JOIN ( SELECT cte.displacement ,
MAX(cte.numGuns) AS MaxNumGun
FROM cte
GROUP BY cte.displacement
) AS M ON cte.displacement = M.displacement
AND cte.numguns = M.MaxNumGun
输出