假设我有一个包含三列和以下数据的表:
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
答案 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