2014-09-05 14 views
5

Potrzebuję szeregować wartości w ruchomym oknie czasowym. Dostałem wskazówki od blogu Tony'ego Haslera pod adresem https://tonyhasler.wordpress.com/2012/10/24/model-clause-use-cases/#comment-5116, ale rozwiązanie polegające na dodaniu klauzuli okienkowania do funkcji innych niż okienkowe, takich jak mediana, nie działa z funkcjami rank() lub percent_rank(), które są analitycznymi funkcjami innymi niż okna.Jak dodać ruchome okno do rangi() używając Oracle SQL

przykład Praca z medianą function():

with a as (
    select 'a' sector, trunc(sysdate) dt, 64 v from dual union all 
    select 'a' sector, trunc(sysdate)-1 dt, 2 from dual union all 
    select 'a' sector, trunc(sysdate)-2 dt, 4 from dual union all 
    select 'a' sector, trunc(sysdate)-3 dt, 128 from dual union all 
    select 'a' sector, trunc(sysdate)-4 dt, 8 from dual union all 
    select 'a' sector, trunc(sysdate)-5 dt, 16 from dual union all 
    select 'a' sector, trunc(sysdate)-6 dt, 32 from dual union all 
    select 'a' sector, trunc(sysdate)-7 dt, 256 from dual union all 
    select 'a' sector, trunc(sysdate)-8 dt, 1 v from dual union all 
    select 'a' sector, trunc(sysdate)-9 dt, 512 from dual union all 
    select 'b' sector, trunc(sysdate) dt, 3 from dual union all 
    select 'b' sector, trunc(sysdate)-1 dt, 27 from dual union all 
    select 'b' sector, trunc(sysdate)-2 dt, 9 from dual union all 
    select 'b' sector, trunc(sysdate)-3 dt, 81 from dual 
) 
select * from a 
model 
partition by (sector) 
dimension by (dt) 
measures (v, 0 mov_rank) 
rules 
(
    mov_rank[ANY] = median(v)[dt between CV()-3 and CV()] 
) 
order by sector, dt 
; 

Przykład nie działa, jeśli wymienimy medianę z rankingu(), jak w:

with a as (
    select 'a' sector, trunc(sysdate) dt, 64 v from dual union all 
    select 'a' sector, trunc(sysdate)-1 dt, 2 from dual union all 
    select 'a' sector, trunc(sysdate)-2 dt, 4 from dual union all 
    select 'a' sector, trunc(sysdate)-3 dt, 128 from dual union all 
    select 'a' sector, trunc(sysdate)-4 dt, 8 from dual union all 
    select 'a' sector, trunc(sysdate)-5 dt, 16 from dual union all 
    select 'a' sector, trunc(sysdate)-6 dt, 32 from dual union all 
    select 'a' sector, trunc(sysdate)-7 dt, 256 from dual union all 
    select 'a' sector, trunc(sysdate)-8 dt, 1 v from dual union all 
    select 'a' sector, trunc(sysdate)-9 dt, 512 from dual union all 
    select 'b' sector, trunc(sysdate) dt, 3 from dual union all 
    select 'b' sector, trunc(sysdate)-1 dt, 27 from dual union all 
    select 'b' sector, trunc(sysdate)-2 dt, 9 from dual union all 
    select 'b' sector, trunc(sysdate)-3 dt, 81 from dual 
) 
select * from a 
model 
partition by (sector) 
dimension by (dt) 
measures (v, 0 mov_rank) 
rules 
(
    mov_rank[ANY] = rank() over (order by v)[dt between CV()-3 and CV()] 
) 
order by sector, dt 
; 

Będę wdzięczny za każdą pomoc.

Dzięki.

+0

Ranke() to literówka? – Bulat

Odpowiedz

2

To może być trochę „staromodny”, ale może być w stanie osiągnąć takich samych wyników przy użyciu samosprzężenie zamiast Analytics lub model, jak na coś takiego:

with a as (
    select 'a' sector, trunc(sysdate) dt, 64 v from dual union all 
    select 'a' sector, trunc(sysdate)-1 dt, 2 from dual union all 
    select 'a' sector, trunc(sysdate)-2 dt, 4 from dual union all 
    select 'a' sector, trunc(sysdate)-3 dt, 128 from dual union all 
    select 'a' sector, trunc(sysdate)-4 dt, 8 from dual union all 
    select 'a' sector, trunc(sysdate)-5 dt, 16 from dual union all 
    select 'a' sector, trunc(sysdate)-6 dt, 32 from dual union all 
    select 'a' sector, trunc(sysdate)-7 dt, 256 from dual union all 
    select 'a' sector, trunc(sysdate)-8 dt, 1 v from dual union all 
    select 'a' sector, trunc(sysdate)-9 dt, 512 from dual union all 
    select 'b' sector, trunc(sysdate) dt, 3 from dual union all 
    select 'b' sector, trunc(sysdate)-1 dt, 27 from dual union all 
    select 'b' sector, trunc(sysdate)-2 dt, 9 from dual union all 
    select 'b' sector, trunc(sysdate)-3 dt, 81 from dual 
) 
select 
    a.sector, 
    a.dt, 
    a.v, 
    count(case when self.v < a.v then self.v end) + 1 mov_rank 
from 
    a, 
    a self 
where 
    self.sector = a.sector 
    and 
    self.dt between a.dt - 3 and a.dt + 3 
group by 
    a.sector, 
    a.dt, 
    a.v 
order by 
    a.sector, 
    a.dt, 
    a.v; 
Powiązane problemy