【问题标题】:Calculation total Contribution based on total score and Grades根据总分和成绩计算总贡献
【发布时间】:2021-03-01 15:07:56
【问题描述】:

我有一个场景,需要根据总得分和成绩进行计算。 以下是 2 名球员的得分。

以下是需要申请的等级范围。总分是115,第一名优先。所以计算将从0-50,50-100和100-150开始。

所以 sachin 将有 70 个运行,其中 50 个将在 1 级以下,其余 20 个在 2 级。 Dhoni 将从 70 开始,并在 2 年级以下填充 45 到 100 中的 30。 100后,Dhoni剩下的15个将被添加到3级。

正在查找基于表 date 1 和 2 执行计算部分的查询。 表 3 是预期的查询输出。

【问题讨论】:

  • 您如何决定先考虑 Sachin 的跑步,然后再考虑 Dhoni 的跑步?您可以先使用 Dhoni,然后使用 Sachin,结果会有所不同。另外,当你解释你的规则时,还要解释当有关系时必须做什么。 (例如,如果您说“我从 Sachin 开始,因为他的跑数比 Dhoni 多”,那么如果他们的跑数相同,规则是什么?)此外,如果您在答案中的任何地方说“它没有无论如何,任何顺序都可以”,请确保这实际上是真实的并且在现实生活中的问题中是可以接受的。
  • 感谢您的反馈,我将通过添加另一个说明优先级的列来更新详细信息。
  • 还有两个问题...首先,如果总数大于150怎么办?最后一个“等级”不应该是无限范围(101到无穷大)吗?无论如何,如果总数大于 150,输出中应该显示什么?其次,您是否可以控制表格的结构? grades 表应仅显示每个范围的上限(50 - 1 级、100 - 2 级、150(或null 表示“无限”)- 3 级等)
  • 我会说如果大于 150 使用 4 .150-Inifinvity 将是 4

标签: oracle plsqldeveloper


【解决方案1】:

首先让我们设置数据。我从三个表开始:players(每个玩家一行;这包括一个 id、名称和优先级 - 优先级不应出现在“分数”表中); grades 就像您的问题一样(尽管它应该看起来更像是我在下面的 with 子句中定义的 g 子查询的结果);和runs_scored,显示每场比赛和每位球员的得分。 重要提示 - 还应该有一个matches 表格(包含比赛ID 和其他详细信息,例如日期、主队、客队等);我很懒,只是从runs_scored 表中提取了匹配ID。

好的,所以数据设置如下所示:

创建或重新创建表(如果它们已经存在,请先删除它们)

drop table runs_scored purge;
drop table players     purge;
drop table grades      purge;

create table players (
  player_id number       primary key
, name      varchar2(20) not null
, priority  number       not null unique
);

create table grades (
  range     varchar2(20) primary key
, grade     number       not null unique
);

create table runs_scored (
  match_id  number not null -- references matches (should have that table too)
, player_id number references players
, score     number not null
, primary key (match_id, player_id)
);

填充表格

insert into players
  select 1001, 'Sachin', 1 from dual union all
  select 1002, 'Dhoni' , 2 from dual union all
  select 1005, 'Ravi'  , 3 from dual
;

insert into grades
  select '0-50'   , 1 from dual union all
  select '50-100' , 2 from dual union all 
  select '100-150', 3 from dual
;

insert into runs_scored
  select 1, 1001,  70 from dual union all
  select 1, 1002,  45 from dual union all
  select 3, 1005,  50 from dual union all
  select 3, 1002,  50 from dual union all
  select 3, 1001,  50 from dual union all
  select 8, 1002, 160 from dual union all
  select 9, 1001,  40 from dual union all
  select 9, 1005,   0 from dual union all
  select 9, 1002,  15 from dual
;

commit;

请注意,我假设必须为每场比赛单独分配成绩;如果不是这种情况,可以轻松修改查询,以应用所有比赛中总得分的成绩。

在输出中,我将排除未出现在runs_scored 表中的玩家,以及可能出现得分为 0 的奇数玩家(并且可能不应该包含在第一个地方)。当然,你可以有一个约束,首先要求分数 > 0。

那么这里有一种方法可以做到这一点,充分利用分析功能:

查询

with
  g (runs, grade) as (
    select to_number(substr(range, instr(range, '-') + 1)), grade from grades
    union all
    select null, 1 + max(grade) from grades
  )
, matches (match_id) as (   -- there should be a MATCHES table; simulated here
    select distinct match_id from runs_scored
  )
, prep (match_id, player_id, name, priority, score, cumul_score, grade) as (
    select rs.match_id, rs.player_id, p.name, p.priority, rs.score,
           sum(rs.score) over (partition by rs.match_id order by p.priority),
           cast (null as number)
      from runs_scored rs join players p on rs.player_id = p.player_id
    union all
    select m.match_id, null, null, null, null, g.runs, g.grade
      from matches m cross join g
  )
, comps (match_id, cumul_score, player_id, name, score, grade) as (
    select match_id, cumul_score,
           last_value(player_id ignore nulls) over (partition by match_id
                                order by cumul_score desc, priority desc),
           last_value(name ignore nulls) over (partition by match_id
                                order by cumul_score desc, priority desc),
           cumul_score - lead(cumul_score, 1, 0) over (partition by match_id
                                order by cumul_score desc, priority desc),
           last_value(grade ignore nulls) over (partition by match_id
                                order by cumul_score desc, priority desc)
    from   prep p
  )
select match_id, player_id, name, score, grade, score * grade as final
from   comps
where  name is not null and score > 0
order  by match_id, cumul_score;

输出

  MATCH_ID  PLAYER_ID NAME       SCORE GRADE      FINAL
---------- ---------- ---------- ----- ----- ----------
         1       1001 Sachin        50     1         50
         1       1001 Sachin        20     2         40
         1       1002 Dhoni         30     2         60
         1       1002 Dhoni         15     3         45
         3       1001 Sachin        50     1         50
         3       1002 Dhoni         50     2        100
         3       1005 Ravi          50     3        150
         8       1002 Dhoni         50     1         50
         8       1002 Dhoni         50     2        100
         8       1002 Dhoni         50     3        150
         8       1002 Dhoni         10     4         40
         9       1001 Sachin        40     1         40
         9       1002 Dhoni         10     1         10
         9       1002 Dhoni          5     2         10

要了解这是如何工作的,在with 子句中的每个连续子查询之后中断代码并从该子查询到select * 可能会有所帮助。您将看到每个步骤的作用。

【讨论】:

  • 感谢您的帮助,如果需要,我将使用查询并进行一些更改并让您知道。不得不说这令人印象深刻,我很想达到这个阶段。
猜你喜欢
  • 2017-03-03
  • 1970-01-01
  • 2015-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-31
  • 2017-01-19
相关资源
最近更新 更多