【问题标题】:Query complex in Oracle SQLOracle SQL 中的复杂查询
【发布时间】:2019-05-11 00:44:19
【问题描述】:

我有以下表格及其字段

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

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

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

【问题讨论】:

    标签: sql oracle oracle11g


    【解决方案1】:

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

    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'
      

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

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

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

    • 建议我们 - 作为开发人员 - 使用显式表连接,让您查看与过滤器分离的所有连接(这应该是 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'
      
    • 然后移动到另一个表,依此类推。

    • 始终频繁测试 - 不要跳过步骤。仅当您确定上一步的结果正确时才继续执行另一个,因为在大多数情况下,它不会自动修复。

    【讨论】:

    • (赞成!)显然,他们也需要 SPORTS 表——因为需要“艺术体操”(稍后可能会在 WHERE 子句中提到)——所以:缺少一个 JOIN .不过,主要困难似乎是使用 AVG() 和 TRUNC() 的嵌套函数调用。也许您可以添加一些代码来演示这一点。
    • @Littlefoot 我的问题是,在所有示例中,我从未使用过联接或左联接,总是在表之间使用相等性,我的意思是,加入表总是使用“NameTable.FieldTable”= “名称表.字段表”。另一方面,试试你给我的,我一点一点地去,年龄问题不起作用,它告诉我“错误不一致的数据类型:预期的数字得到了日期”,我想这是因为生日字段是字符类型。另一方面,他们要求我按平均年龄排序。平均年龄是多少?我很接近,但仍有疑问
    • @stefan 真的是“艺术体操”运动,我已经用它的 idSport 拿出了它 = 18,我已经拥有它了。我需要考虑到当前日期“Sysdate”以及生日字段是char类型的问题来获取每个体操运动员的年龄,并且您会看到平均值,如您所说的avg ...但不要使用它。我很接近,但我无法得到它。
    • @Roman345 如果日期存储为varchar2,则需要将其转换为DATE。我已经为你写了一个小例子(包括 TO_DATE()、SYSDATE、TRUNC() 和 AVG()),在一个小表中使用你问题的前 3 个 BIRTHDATE。见dbfiddle.uk/…
    • @stefan 数据是一个 CHAR (10 BYTE),例如输入到数据库 '22 / 05/2018' 中。使用你给我的东西: select trunc (avg (sysdate - to_date (person.birthday, 'DD / MM / YYYY'))) trunc_avg_diff from person;但我得到错误:ORA-00932:不一致的数据类型:预期的 NUMBER 得到了 DATE 00932。00000 -“不一致的数据类型:预期的%s 得到了%s”除了我必须将它划分为 365,我注意到我是,我们非常接近但我不明白。关于你认为的连接?我们不使用它们,我们使用均衡器。
    猜你喜欢
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-22
    • 2018-02-19
    • 1970-01-01
    相关资源
    最近更新 更多