Расстояние от максимального значения для каждого расстояния - PullRequest
0 голосов
/ 04 октября 2018

Я хотел бы рассчитать расстояние до максимального значения для каждого возможного расстояния.В качестве примера:

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 голосов
/ 04 октября 2018
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
;
0 голосов
/ 04 октября 2018

Вы можете использовать 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.Выберите то, что вы хотите.

0 голосов
/ 04 октября 2018

Вы можете получить максимальное значение, используя совокупный максимум:

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;
...