sql-ex.ru选择语句练习51

时间:2016-10-18 07:04:30

标签: sql-server tsql

我正在关注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

1 个答案:

答案 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

输出

enter image description here