通过SQL查询球员的平均热身时间

时间:2018-09-20 02:16:49

标签: sql oracle

假设我有一个包含三列和以下数据的表:

const myobservable(a, b) = new Observable((observer) => {
  ...
})

我正在寻找一个* gamedate,playername,pointsScored * 20180101,George,34 * 20180102,George,37 * 20180103,George,38 * 20180104,George,3 * 20180105,George,35 * 20180106,George,37 * 20180107,George,31 * 20180108,George,31 * 20180109,George,32 * 20180110,George,7 ,该数字告诉我该玩家平均可以连续保持30多个得分。我知道它一定是某种sql query函数,但是我对如何制定此查询有些困惑。如果有任何区别,这是group by

一些额外的测试日期:

Oracle table

2 个答案:

答案 0 :(得分:4)

在Oracle 12.1或更高版本中,MATCH_RECOGNIZE子句可以快速完成此类分配:

with
  inputs(gamedate,playername,pointsscored) as (
    select to_date('20180101','yyyymmdd'), 'George', 34 from dual union all
    select to_date('20180102','yyyymmdd'), 'George', 37 from dual union all
    select to_date('20180103','yyyymmdd'), 'George', 38 from dual union all
    select to_date('20180104','yyyymmdd'), 'George',  3 from dual union all
    select to_date('20180105','yyyymmdd'), 'George', 35 from dual union all
    select to_date('20180106','yyyymmdd'), 'George', 37 from dual union all
    select to_date('20180107','yyyymmdd'), 'George', 31 from dual union all
    select to_date('20180108','yyyymmdd'), 'George', 31 from dual union all
    select to_date('20180109','yyyymmdd'), 'George', 32 from dual union all
    select to_date('20180109','yyyymmdd'), 'George',  7 from dual
  )
select playername, avg(cnt) as average_streak
from   inputs
match_recognize(
  partition by playername
  order by     gamedate
  measures     count(*) as cnt
  one row per match
  pattern ( a+ )
  define a as pointsscored >= 30
)
group by playername
;

PLAYER AVERAGE_STREAK
------ --------------
George              4

说明:

MATCH_RECOGNIZE按玩家划分输入行,并按游戏日期在每个分区内排序。 “匹配”是指一个或多个连续的行(在a+子句中的PATTERN)得到了30分以上的得分(请参见DEFINE子句)。 MATCH_RECOGNIZE为其找到的每个匹配项返回一行,具体来说,它将返回玩家名称和该匹配项中的行数(即连胜的长度,连续行数或游戏数)。外部查询按玩家分组,并获取平均条纹长度。

答案 1 :(得分:1)

这是一种方法。它使用Tabibitosan(或“固定差异”)方法来识别条纹-这是内部查询中两个ROW_NUMBER调用的差异。其余的是分组并采用聚合函数。

WITH子句用于模拟数据;它不是解决方案的一部分,应在对实际数据测试解决方案之前将其删除。 (在内部查询中使用实际的表名而不是INPUTS。)

with
  inputs(gamedate,playername,pointsscored) as (
    select to_date('20180101','yyyymmdd'), 'George', 34 from dual union all
    select to_date('20180102','yyyymmdd'), 'George', 37 from dual union all
    select to_date('20180103','yyyymmdd'), 'George', 38 from dual union all
    select to_date('20180104','yyyymmdd'), 'George',  3 from dual union all
    select to_date('20180105','yyyymmdd'), 'George', 35 from dual union all
    select to_date('20180106','yyyymmdd'), 'George', 37 from dual union all
    select to_date('20180107','yyyymmdd'), 'George', 31 from dual union all
    select to_date('20180108','yyyymmdd'), 'George', 31 from dual union all
    select to_date('20180109','yyyymmdd'), 'George', 32 from dual union all
    select to_date('20180109','yyyymmdd'), 'George',  7 from dual
  )
select   playername, avg(ct) as average_streak
from     (
           select playername, count(*) as ct
           from   (
                    select playername, pointsscored,
                           row_number() over (partition by playername 
                                                order by gamedate)
                           - row_number() over (partition by playername,
                                                 case when pointsscored >= 30 
                                                      then 0 end
                                                 order by gamedate) as grp
                    from   inputs
                  )
           group by playername, grp
           having   min(pointsscored) >= 30
         )
group by playername
order by playername
;

输出

PLAYER AVERAGE_STREAK
------ --------------
George              4