表:
Classes (class, type, country, numGuns, bore, displacement)
Ships (name, class, launched)
Outcome (ship, battle, result)
问题:
为每个班级找出在战斗中沉没的那个级别的船只数量。
我的回答:
SELECT ships.class, COUNT(*)
FROM ships, outcome
WHERE ships.name = outcomes.ship AND outcome.result = 'sunk'
GROUP BY ships.class
回答加入:
SELECT class, COUNT(*)
from ships
inner join outcomes
on name = ship
where outcome.result = 'sunk'
group by class
样本小册子中给出的答案:
SELECT classes.class, COUNT(*)
FROM classes, ships, outcomes
WHERE classes.class = ships.class AND ship = name AND result = 'sunk'
GROUP BY classes.class;
我没有得到的是为什么他们必须包含classes
表,这不是我的查询足够吗?我正在做同样的事情,但没有加入classes
表。提前谢谢。
答案 0 :(得分:2)
唯一真正的区别是,如果有一个没有船只的班级,所提供的答案将包含一行,而您的查询则不会。
哎呀,对不起,我最初误读了示例答案。他们之间没有真正的区别。
值得注意的是这种语法:
SELECT classes.class, COUNT(*)
FROM classes, ships, outcomes
WHERE classes.class = ships.class AND ship = name AND result = 'sunk'
GROUP BY classes.class;
过时且不赞成使用。这是首选的现代语法:
SELECT classes.class, COUNT(*)
FROM classes
INNER JOIN ships ON classes.class = ships.class
INNER JOIN outcomes ON outcomes.ship = ships.name
WHERE outcomes.result = 'sunk'
GROUP BY classes.class;
答案 1 :(得分:1)
我会投票通过Kaczmarski,因为它非常接近。有效的答案还有一行可以在第二遍传递错误检查。
需要检查以确保ships.name
不包含也是类名的名称。
一个有效的数据库结构将包括俾斯麦号和所有在结果表中以及船舶表中沉没的船只。或者船只表中不包含任何沉没的船只。
此类方法必须在真实世界的场景中使用,在该场景中,多个用户正在修改数据库,并且用户对正在修改的表具有读访问权。
select class, sum(sunks) as sunks from(
select class, sum(case result when 'sunk' then 1 else 0 end) as sunks
from classes c left join outcomes o on c.class = o.ship
where class not in (select name from ships)
group by class
union all
select class, sum(case result when 'sunk' then 1 else 0 end) as sunks
from ships s left join outcomes o on s.name = o.ship
group by class
)as x
group by class
答案 2 :(得分:1)
更有效的方法是:
select class, SUM(CASE WHEN result='sunk'
THEN 1
ELSE 0 END) from
(
select class,ship as name,result from classes cc left outer join outcomes oo ON cc.class=oo.ship
union
select class,name,result from ships ss left outer join outcomes oo ON ss.name=oo.ship
) as ttt
group by class
答案 3 :(得分:1)
对于每个类别,此查询将返回沉没的船舶数量,因此,如果没有沉没的船舶,您将获得0计数,而不是仅显示沉没了船舶的类别。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def root():
return "Hello World"
这是输出的样子
select class, count(ship) as Sunk_Count
from ships left outer join
(select outcomes.ship
from Outcomes
where result = 'Sunk') as result
on Ships.name = result.ship
group by class
希望这会有所帮助!
答案 4 :(得分:1)
我知道这是一个老问题,但我希望这对任何试图找出此练习答案的人有所帮助
outcomes
表可以包含未包含在 ships
表中的船舶。
您的查询仅包括 ships
表中的船舶,您需要包括 outcomes
表中的一些船舶。问题是,如何知道结果船属于哪个等级?。
练习中给出了一些笔记
<块引用>结果关系可能包含船舶中不存在的船舶 关系。
沉没的舰船无法参加以后的战斗。
由于历史原因,领航舰在 许多练习。
在 Outcomes 表中找到但在 Ships 表中没有的船是 仍然在数据库中考虑。即使它沉没了也是如此。
classes
表还有一个语句
名称被分配到一个等级的船称为领头船。
基于此,您可以通过以下查询获得所有船只
SELECT name FROM ships
UNION
SELECT ship FROM outcomes o
JOIN classes c ON (o.ship = c.class)
如果一艘船不存在于 ships
表中,但存在于 outcomes
表中,那么知道它的等级的唯一方法是将船舶的名称与所有等级进行比较,如果有一场比赛,这艘船是一艘领头船。
这是一个可以为您提供正确答案的查询示例
WITH all_ships AS (
SELECT name FROM ships
UNION
SELECT ship FROM outcomes o
JOIN classes c ON (o.ship = c.class)
),
ships_sunked AS (
SELECT name FROM all_ships
JOIN outcomes o ON (o.ship = all_ships.name)
WHERE o.result = 'sunk'
)
SELECT DISTINCT COALESCE(class, ss.name) FROM ships s
RIGHT JOIN ships_sunked ss ON (s.name = ss.name)
答案 5 :(得分:0)
两个查询都没有真正的区别。如果您从select中删除group by和count,则可能会有所不同。因为在不同的类中可以有多个相同的船名。由于您逐个使用组,因此它们在两个查询中都没有任何区别。两个查询都将返回每班的船只数量。
答案 6 :(得分:0)
这对你的TA(助教?)提出一个很好的问题。可能存在“教学”原因,为什么会使用您书中的答案。
虽然您的查询和书中的查询会产生相同的结果,但您的查询无法轻易修改以回答有关“类”的其他问题。例如,假设问题变为“每个国家有多少船沉没?”。对“书籍查询”进行简单的更改就可以轻松实现(使用RBarryYoung重新格式化的代码):
SELECT classes.country, COUNT(*)
FROM classes
INNER JOIN ships ON classes.class = ships.class
INNER JOIN outcomes ON outcomes.ship = ships.name
WHERE outcomes.result = 'sunk'
GROUP BY classes.country;
这可能是一个微妙的问题,但是使用您“最感兴趣”的表作为FROM
子句启动查询,然后根据需要加入其他相关表。这至少使您的代码更容易阅读。
答案 7 :(得分:0)
您的查询不会列出每个船只沉没的类别 这有点好,但似乎仍然不正确:
select class, sum(sunks) as sunks from(
select class, sum(case result when 'sunk' then 1 else 0 end) as sunks
from classes c left join outcomes o on c.class = o.ship
group by class
union all
select class, sum(case result when 'sunk' then 1 else 0 end) as sunks
from ships s left join outcomes o on s.name = o.ship
group by class
)as x
group by class
答案 8 :(得分:0)
最简单的答案......
SELECT class,
SUM(CASE WHEN result='sunk' THEN 1 ELSE 0 END)
FROM
(
SELECT class, ship, result
FROM Classes c
LEFT JOIN Outcomes o
ON o.ship=c.class
UNION
SELECT class, ship, result
FROM Ships s
LEFT JOIN Outcomes o
ON o.ship=s.class OR o.ship=s.name
)
AS res
GROUP BY class