首页 > 解决方案 > Oracle SQL 中的复杂查询

问题描述

我有以下表格及其字段

在此处输入图像描述

他们问我一个在我看来相当复杂的查询,我已经走了两天并尝试了一些事情,它说:

对于不同形式的“艺术体操”,希望获得女运动员、奖牌获得者(金牌、银牌或铜牌)的平均年龄。分析结果字段的可能内容以便仅返回预期值,即使查询显示的记录集没有任何特定值的数据。具体来说,我们要显示运动员的性别指标、获得的奖牌以及这些运动员的平均年龄。年龄的计算方法是从系统日期(SYSDATE)中减去运动员的出生日期,再除以 365。为了避免显示小数,截断(TRUNC)年龄计算的结果。按运动员的平均年龄排列结果。

好吧,现在我有这个:

select person.gender,score.score
from person,athlete,score,competition,sport
where person.idperson = athlete.idathlete    and
athlete.idathlete=  score.idathlete  and
competition.idsport = sport.idsport and
person.gender='F' and competition.idsport=18 and score.score in 
('Gold','Silver','Bronze')
group by 
person.gender,
score.score;

我把这个弄出来了

在此处输入图像描述

通过添加 person.birthdate 字段而不是留下 18 个人获得奖章的 18 条记录,我将获得更多记录。

除此之外,我仍然需要使用 SYSDATE 和 TRUNC 绘制平均年龄,我尝试了很多方法,但我不明白。

在此处输入图像描述

我觉得这很复杂,或者我因为太多的旋转而有点饱和,我需要一些帮助。

标签: sqloracleoracle11g

解决方案


阅读你得到的任务,似乎你已经很接近解决方案了。查看以下查询及其解释,注意与您的查询的差异,看看它是否有帮助。

select p.gender,
       ((sysdate - p.birthday) / 365) age,
       s.score
from person p join athlete a on a.idathlete = p.idperson       
              left join score s on s.idathlete = a.idathlete
              left join competition c on c.idcompetition = s.idcompetition
where p.gender = 'F'
  and s.score in ('Gold', 'Silver', 'Bronze')
  and c.idsport = 18
order by age;
  • 当减去两个日期时,结果是天数。将它除以 365,您 - 大致 - 得到年数(因为每年有 365 天 - 当然,这是为了简单起见,因为并非所有年份都有那么多天(提示:闰年))。结果通常是十进制数,例如23.912874918724。为了避免这种情况,您被告知要删除小数,所以 - 使用TRUNC并得到23结果
  • 尽管数据模型包含 5 个表,但您不必在查询使用所有表。也许最好的方法是一步一步来。第一个是简单地选择所有女运动员并计算她们的年龄:

    select p.gender,
           ((sysdate - p.birthday) / 365 age
    from person p
    where p.gender = 'F'
    

    请注意,我使用了表别名- 我建议您也使用它们,因为它们使查询更易于阅读(表名可以有很长的名称,这对可读性没有帮助)。此外,始终使用表别名以避免混淆(哪个列属于哪个表)

  • 一旦您对该结果感到满意,请转到另一个表 -athlete它在这里只是作为与包含...的表的连接机制......好吧, score。请注意,我对表格使用了外连接,因为并非所有运动员都赢得了奖牌。我想这就是你被赋予的任务所说的:scorescore

    ...即使查询显示的记录集没有任何特定值的数据。

  • 建议我们 - 作为开发人员 - 使用显式表连接,让您查看与过滤器分离的所有连接(这应该是WHERE子句的一部分)。所以:

    NO : from person p, athlete a
         where a.idathlete = p.idperson
           and p.gender = 'F'
    
    YES: from person p join athlete a on a.idathlete = p.idperson
         where p.gender = 'F'
    
  • 然后移动到另一张桌子,依此类推。

  • 经常测试,所有时间 - 不要跳过步骤。仅当您确定上一步的结果正确时才继续进行另一个,因为在大多数情况下,它不会自动修复自身。

推荐阅读