每个距离与最大值的距离

时间:2018-10-04 13:30:53

标签: sql oracle oracle12c

我想为每个可能的距离计算最大距离。例如:

Row  Distance Value
1     1        2     --> 1 (Distance from Row 1)
2     2        3     --> 2 (Distance from Row 2)
3     3        3     --> 2 (Distance from Row 2)
4     4        1     --> 2 (Distance from Row 2)
5     5        5     --> 5 (Distance from Row 5)
6     6        1     --> 5 (Distance from Row 5)

说明:第6行的值为5,因为第1到6行之间的最大值的第一次出现是在距离5处。

我尝试使用一些Windows函数,但无法弄清楚如何将其组合在一起。

样本数据:

--drop table tmp_maxval;
create table tmp_maxval (dst number, val number);
insert into tmp_maxval values(1, 3);
insert into tmp_maxval values(2, 2);
insert into tmp_maxval values(3, 1);
insert into tmp_maxval values(4, 2);
insert into tmp_maxval values(5, 4);
insert into tmp_maxval values(6, 2);
insert into tmp_maxval values(7, 2);
insert into tmp_maxval values(8, 5);
insert into tmp_maxval values(9, 5);
insert into tmp_maxval values(10,1);
commit;

我认为功能可以解决以下问题:

select t.*, 
       max(val) over(order by dst), 
       case when val >= max(val) over(order by dst) then 1 else 0 end ,        
       case when row_number() over(partition by val order by dst) = 1 then 1 else 0 end as first_occurence
from 
  ap_risk.tmp_maxval t

3 个答案:

答案 0 :(得分:3)

select dst, val, 
       max(case when flag is null then dst end) over (order by dst) 
         as first_occurrence
from   (
         select dst, val, 
                case when val <= max(val) over (order by dst 
                             rows between unbounded preceding and 1 preceding)
                then 1 end as flag
         from tmp_maxval
       )
order by dst
;

       DST        VAL FIRST_OCCURRENCE
---------- ---------- ----------------
         1          3                1
         2          2                1
         3          1                1
         4          2                1
         5          4                5
         6          2                5
         7          2                5
         8          5                8
         9          5                8
        10          1                8

或者,如果您使用的是Oracle 12.1或更高版本,MATCH_RECOGNIZE可以快速完成此任务:

select dst, val, first_occurrence
from   tmp_maxval t
match_recognize(
  order by dst
  measures a.dst as first_occurrence
  all rows per match
  pattern  (a x*)
  define   x as val <= a.val
)
order by dst
;

答案 1 :(得分:0)

您可以将max()min()case when结合使用:

select t.*, 
       min(case when val = mv then dst end) over (partition by mv order by dst) v1,
       max(case when val = mv then dst end) over (partition by mv order by dst) v2
  from (select t.*, max(val) over (order by dst) mv from tmp_maxval t) t 
  order by dst

结果:

       DST        VAL         MV         V1         V2
---------- ---------- ---------- ---------- ----------
         1          3          3          1          1
         2          2          3          1          1
         3          1          3          1          1
         4          2          3          1          1
         5          4          4          5          5
         6          2          4          5          5
         7          2          4          5          5
         8          5          5          8          8
         9          5          5          8          9
        10          1          5          8          9

解释的逻辑和单词第一次出现表示您需要min(),但是示例中的第三行建议max() ;-)在您提供的数据中,您可以观察到差异在9-10行中。选择您想要的。

答案 2 :(得分:-1)

您可以使用累积最大值获得最大值:

select mv.*, max(mv.value) over (order by mv.distance) as max_value
from ap_risk.tmp_maxval mv;

我认为这可以回答您的问题。如果您想要距离本身:

select mv.*,
       min(case when max_value = value then distance end) over (order by distance) as first_distance_at_max_value
from (select mv.*, max(mv.value) over (order by mv.distance) as max_value
      from ap_risk.tmp_maxval mv
     ) mv;