oraclesql中的复杂查询

oraclesql中的复杂查询,sql,oracle,oracle11g,Sql,Oracle,Oracle11g,我有以下表格及其字段 他们问我一个在我看来相当复杂的问题,我已经四处奔波了两天,尝试了很多东西,上面写着: 希望获得不同形式的“艺术体操”的女运动员、奖牌获得者(金牌、银牌或铜牌)的平均年龄。分析结果字段的可能内容,以便仅返回预期值,即使查询显示的记录集没有任何特定值的数据。具体来说,我们想显示运动员的性别指标、获得的奖牌以及这些运动员的平均年龄。年龄的计算方法是从系统日期(SYSDATE)中减去运动员的出生日期,再除以365。为了避免显示小数,请截断(TRUNC)年龄计算结果。按运动员的平均

我有以下表格及其字段

他们问我一个在我看来相当复杂的问题,我已经四处奔波了两天,尝试了很多东西,上面写着:

希望获得不同形式的“艺术体操”的女运动员、奖牌获得者(金牌、银牌或铜牌)的平均年龄。分析结果字段的可能内容,以便仅返回预期值,即使查询显示的记录集没有任何特定值的数据。具体来说,我们想显示运动员的性别指标、获得的奖牌以及这些运动员的平均年龄。年龄的计算方法是从系统日期(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张奖牌获得者的记录,我将看到更多的记录

除此之外,我还必须用SYSDATE和TRUNC绘制平均年龄,我尝试了很多方法,但我没有得到它


我觉得它很复杂,或者我已经被这么多的旋转弄得有点饱和了,我需要一些帮助。

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

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'
    
    请注意,我使用了一个表别名,我建议您也使用它,因为它使查询更容易阅读(表名可能有很长的名称,这对可读性没有帮助)。另外,始终使用表别名以避免混淆(哪个列属于哪个表)

  • 一旦你对这个结果感到满意,就转到另一个表-
    atternate
    它在这里就像是一个与
    分数
    表连接的机制,该表包含。。。嗯,分数。请注意,我在
    得分表中使用了外部连接,因为并非所有运动员都获得了奖牌。我想这就是给你的任务所说的:

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

  • 作为开发人员,建议我们使用显式表联接,这样您就可以看到从过滤器中分离出来的所有联接(这应该是
    WHERE
    子句的一部分)。因此:

  • 然后移到另一张桌子,依此类推

  • 经常测试,不要跳过步骤。只有当你确信上一步的结果是正确的时,才能继续下一步,因为在大多数情况下,它不会自动修复自身

(投票赞成!)显然,他们也需要运动桌——因为需要“艺术体操”(稍后可能会在WHERE条款中提及)——所以:缺少一个参赛者。不过,主要的困难似乎是使用AVG()和TRUNC()进行嵌套函数调用。也许您可以添加一些代码来演示这一点。@Littlefoot我的问题是,在所有示例中,我从未使用连接或左连接,总是使用表之间的等式,我的意思是,要连接表,总是使用“NameTable.FieldTable”=“NameTable.FieldTable”。另一方面,试试你给我讲的,我一点一点地讲,年龄问题不起作用,它告诉我“错误不一致的数据类型:预期的数字得到了日期”,我想这是因为生日字段是char类型的。另一方面,他们让我按平均年龄点餐。平均年龄是多少?我很接近,但仍然和你在一起doubts@stefan真的,这项运动“艺术体操”我已经把它拿出来了,它的idSport=18,我已经有了它。我需要考虑到当前日期“Sysdate”和生日字段是char类型的问题,得到每个体操运动员的年龄,你可以看到平均值,正如你所说的平均值。。。但不要使用它。我非常接近,但我无法获取它。@Roman345如果日期存储为varchar2,则需要将其转换为日期。我已经为您编写了一个小示例(包括TO_DATE()、SYSDATE、TRUNC()和AVG()),在一个小表格中使用您问题的前3个生日。请参见@stefan。例如,数据是输入数据库“22/05/2018”中的字符(10字节)。使用您这样描述我的方式:选择trunc(avg(sysdate-to_date(person.birth,'DD/MM/YYYY'))trunc_avg_diff from person;但我得到了错误:ORA-00932:不一致的数据类型:预期数量得到日期00932。00000-“不一致的数据类型:预期的%s得到了%s”除了我必须将其划分为365之外,我注意到我是,我们非常接近,但我没有得到它。关于你认为的连接?我们不使用它们,我们使用均衡。
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'