免责声明:我通过在线教程帮助一个人学习SQL。所以你可以把它当作一个家庭作业问题。
我们在这里处理3个SQL Server表:
现在数据库的布局中有几个疯狂的东西,最大的一个是当Outcomes
表中的船只以同样的方式命名时,它们可能不会出现在Ships
表中作为Class
中的课程。
重点是获得每个级别的沉船数量。我帮助学生学习了以下SQL:
Select
dbo.Classes.[class], Count(dbo.Outcomes.ship) as [count]
from
dbo.Classes
left join
dbo.Ships on dbo.Ships.[class] = dbo.Classes.[class]
left join
dbo.Outcomes on (dbo.Outcomes.ship = dbo.Classes.[class] or
dbo.Outcomes.ship = dbo.Ships.name)
and dbo.Outcomes.result = 'sunk'
Group by
dbo.Classes.[class]
然而,显然,它是不正确的解决方案,因为在某些情况下它可能会返回不正确的结果。在网络上,我设法找到了本教程的以下解决方案:
select
classes.class, count(T.ship)
from
classes
left join
(select
ship, class
from
outcomes
left join
ships on ship = name
where
result = 'sunk'
union
select
ship, class
from
outcomes
left join
classes on ship = class
where
result = 'sunk') as T on classes.class = T.class
group by
classes.class
但我无法理解结果会在哪些条件下有所不同。使用两个不同的连接路径的Union
操作是否与连接条件下的OR
功能完全相同?
P.S。本教程中的这个特定问题实际上标记为2,难度为1-5。所以我觉得自己很蠢。
答案 0 :(得分:3)
在许多情况下,查询可能会返回不同的结果。一个明显的例子是沉船与class
中的name
和outcomes
相匹配。在这种情况下,第二个查询中的union
将返回一行。第一个查询中的join
将返回两行。因此,计数会有所不同。
我认为您可以在第一个查询中使用count(distinct)
来修复此特定问题。
答案 1 :(得分:3)
使用此数据集:
with Ships as (
select * from (values
('HMS Prince of Wales','King George V')
,('King George V','King George V')
)Ships(name,class)
),
Classes as (
select * from (values
('King George V')
)Classes(class)
),
Outcomes as (
select * from (values
('HMS Prince of Wales','sunk')
,('King George V','sunk')
)Outcomes(ship,result)
)
您提供的两个查询分别为:
class count
------------- -----------
King George V 3
class
------------- -----------
King George V 2
区别的原因是 UNION 是一个集合运算符,可以消除重复项(与 UNION ALL 不同),而 OR 运算符不会吨。我们可以通过用UNION ALL替换第二个查询中的UNION来测试这个,现在产生:
class
------------- -----------
King George V 3
就像你提出的第一个解决方案一样。
答案 2 :(得分:1)
需要的目标: "重点是获得每个级别的沉船数量。我帮助学生学习了以下SQL:"
应该分三个步骤创建Sudo代码。你需要将它们分解为工作步骤
select * from class
//create a list of all of the classes that exists in your db
select * from [working previous statement] where results = "sunk"
//create another select statement that uses the previous select statement to refine results
//then refine it to have ships that have been sunk
select count from [[previous statement with the two selects]]
//This create the count of all of the sunk ships.
select count from [[previous statement with the two selects]] group by [previous statement with one select]
//this one should create the individual count of all of the sunken ships based on it's class
select sum from [[your pick of which statement]]
//do a sum
自然你需要进行链接,所以代码应该实现为 从船舶sh,类别cl,结果oc选择船舶,其中sh.class = cl.class和oc.ship = sh.ship和oc.result = sunk group by cl.classes
然后在混合中添加计数步骤。