窗口函数中的Oracle中位数,范围在

6ss1mwsb  于 2023-05-16  发布在  Oracle
关注(0)|答案(2)|浏览(167)

是否有任何解决方法可以在特定间隔范围的窗口内使用MEDIAN函数?我想用途:

MEDIAN(numcolumn) OVER (PARTITION BY a
            ORDER BY date_b RANGE BETWEEN INTERVAL '30' DAY PRECEDING AND CURRENT ROW
            )

Oracle抛出一个错误,因为不允许在这里使用ORDER BY。本声明与AVG合作。有没有什么快速的方法可以让这个窗口函数工作,而不是使用一些缓慢的内部连接来处理大量的数据?

2w3rbyxf

2w3rbyxf1#

这个问题已经被问过很多次了,但是快速回顾一下,我还没有找到一个令人满意的答案。Oracle不允许在MEDIAN中使用ORDER BY子句(尽管它允许在AVG中使用!许多人评论说这是没有意义的,因为MEDIAN从一个无序集合中计算结果,对它进行排序将不会完成任何事情,但这忽略了重要的一点,即为了进行范围窗口(如运行平均值,运行中位数等),您需要指定顺序以创建范围逻辑。因此,不支持ORDER BY意味着您无法像您正在尝试的那样使用ROWS BETWEEN,这是Oracle功能中的一个差距。也许在未来的版本中,他们会解决这个问题。
为了实现你所需要的,我建议如下:

SELECT (SELECT MEDIAN(t2.numcolumn)
          FROM tbl t2
         WHERE t2.a = t1.a
           AND t2.date_b BETWEEN t1.date_b - INTERVAL '30' DAY AND t1.date_b) thirty_day_running_median
  FROM tbl t1

只要确保您在tbl(a,date_b,numcolumn)上有索引即可

thigvfpy

thigvfpy2#

由于median没有公开为具有完整窗口语法支持的分析函数,因此不能将其与窗口规范子句一起使用。
但是,这种限制通常可以使用model子句来推动,在单元格计算中可以使用(不太严格的)聚合函数。
使用偏移量模拟median解析函数的步骤:

  • partition by列放在model的相应子句中。
  • order by列放入dimension by子句中。您将能够通过cv(dimension_name)函数使用这些维度的当前(根据当前处理的行)值指定这些列的相对限制。
  • 如果尺寸值出现了多个,则需要调整model子句,以便它知道应该做什么:
  • 添加unique single reference以忽略有关单元格寻址不唯一的抱怨:我们希望处理逻辑间隔(range between),而不是物理间隔。
  • 使用row_number函数,按所需表达式排序为dimension by。它将允许偏移这个值,相当于rows between(只要每个分区的行号是唯一的)。
  • 添加所有不属于partition bydimension by的表达式作为measures子句:您不必为它们指定规则,但它会将它们暴露给select列表和rules表达式的右侧。
  • 为新计算的表达式(“解析函数”值)添加一些人工/默认值到measures:它会保留结果。

将所有这些结合在一起,我们将使用date_column between cv(date_column) - interval '30' day and CV(date_column)作为计算的参考单元格,并使用median作为该范围内的聚合函数。
结果查询

select *
from sample
model
  /*For model not to comply
    about duplicate dimension value.
    Equivalent of range between.
    For rows between semantics you have to
    add row_number() by the required expressions
    and use it as a dimension value for offsetting*/
  unique single reference
  /*partition_by columns*/
  partition by (id)
  /*order_by column for window*/
  dimension by (dt)
  measures (
    /*other attributes go here*/
    /*an expression to pass as an
      argument for median
    */
    val,
    /*measure for median value*/
    0 as med
  )
  rules update (
    med[any] = 
      median(val)[
        /*window specification*/
        dt between cv(dt) - interval '5' day and cv(dt)
      ]
  )
order by id, dt

为随机生成的数据集(由前三列表示)和5天窗口返回此结果:
| ID| DT|瓦尔|MED|
| --------------|--------------|--------------|--------------|
| 0| 2023-05-10 2023-05-10 2023-05-10|-1|-1|
| 0| 2023-05-12 2023-05-12 2023-05-12|二|二|
| 0| 2023-05-12 2023-05-12 2023-05-12|三|二|
| 0| 2023-05-16 2023-05-16 2023-05-16|五|三|
| 0| 2023-05-17 2023-05-17 2023-05-17|-4个|二点五|
| 0| 2023-05-19 2023-05-19 2023-05-19|六|五|
| 0| 2023-05-24 2023-05-24|-7| -0.5|
| 0| 2023-06-01 2023-06-01 2023-06-01|八|八|
| 0| 2023-06-04 2023-06-04|九|八点五|
| 1| 2023-05-26 2023-05-26|十二岁|十二岁|
| 1| 2023-05-28 2023-05-28 2023-05-28|-16|-2|
| 1| 2023-05-29 2023-05-29 2023-05-29|-19|-16|
| 1| 2023-06-02 2023-06-02|-13|-16|
| 1| 2023-06-03 2023-06-03|十八岁|-1|
| 1| 2023-06-03 2023-06-03|十一|-1|
| 1| 2023-06-04 2023-06-04|十四岁|十二点五|
| 1| 2023-06- 05 2023-06-05 2023-06-05|-10|十一|
| 1| 2023-06- 10 2023-06-10 2023-06-10|十五岁|二点五|
| 1| 2023-06- 12 2023-06-12 2023-06-12| 17个|十六岁|
| 二|2023-06-04 2023-06-04|二十一|二十一|
| 二|2023-06- 10 2023-06-10 2023-06-10|二十六|二十六|
| 二|2023-06-30 - 2023-06-30|二十|二十|
| 二|2023-07-01 2023-07-01|二十三|二十一点五|
| 二|2023-07-04 2023-07-04|二十九|二十三|
| 二|2023-07-06 2023-07-06|二十八|二十三|
| 二|2023-07-12 2023-07-12|二十四|1|
| 二|2023-07-12 2023-07-12|二十二|1|
| 二|2023-07-16 2023-07-16 2023-07-16|二十七个|二十四|
| 二|2023-07-18 2023-07-18 2023-07-18|二十五|1|
fiddle

相关问题