【问题标题】:How do I add a moving window to rank() using Oracle SQL如何使用 Oracle SQL 将移动窗口添加到 rank()
【发布时间】:2014-09-05 13:05:04
【问题描述】:

我需要在移动的时间窗口内对值进行排名。我从 Tony Hasler 的一篇博文中得到了一些指导 https://tonyhasler.wordpress.com/2012/10/24/model-clause-use-cases/#comment-5116 但是将窗口子句添加到非窗口函数(如中位数)的解决方案不适用于作为分析非窗口函数的 rank() 或 percent_rank() 函数。

具有中值()函数的工作示例:

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
;

如果我们用 rank() 替换中位数,则示例不起作用,如下所示:

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
;

我将不胜感激。

谢谢。

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    这可能有点“过时”,但您可以使用自联接而不是分析或model 来获得等效结果,例如:

    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;
    

    【讨论】:

      猜你喜欢
      • 2012-11-11
      • 1970-01-01
      • 2010-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多