Как рассчитать медиану ухода с использованием аналитической функции PL / SQL - PullRequest
0 голосов
/ 31 декабря 2018

Я пытаюсь написать аналитическую функцию на PL / SQL, которая при применении к столбцу в таблице возвращает для каждой строки таблицы медиану столбца, исключая данную строку.

Пример для пояснения: Предположим, у меня есть таблица TABLE, состоящая из одного столбца X, которая принимает следующие значения:

1
2
3 
4 
5 

Я хочу определить аналитическую функцию LOOM () такую, что:

SELECT LOOM(X)
FROM TABLE

обеспечивает следующее:

3.5
3.5
3
2.5
2.5 

, т.е. для каждой строки медиана X, исключая данную строку.Я изо всех сил пытался построить желаемую функцию LOOM ().

1 Ответ

0 голосов
/ 31 декабря 2018

Я не уверен, есть ли «умный» способ сделать это.Вы можете выполнить расчет с помощью коррелированного подзапроса.

Предполагая, что значения x уникальны - как в вашем примере -

with t as (
      select 1 as x from dual union all
      select 2 as x from dual union all
      select 3 as x from dual union all
      select 4 as x from dual union all
      select 5 as x from dual
     )
select t.*, 
       (select median(x)
        from t t2
        where t2.x <> t.x
       ) as loom
from t;

РЕДАКТИРОВАТЬ:

Aболее эффективный метод использует аналитические функции, но требует более прямого вычисления медианы.Например:

with t as (
      select 1 as x from dual union all
      select 2 as x from dual union all
      select 3 as x from dual union all
      select 4 as x from dual union all
      select 5 as x from dual
     )
select t.*, 
       (case when mod(cnt, 2) = 0
             then (case when x <= candidate_1 then candidate_2 else candidate_1 end)
             else (case when x <= candidate_1 then (candidate_2 + candidate_3)/2 
                        when x = candidate_2 then (candidate_1 + candidate_3)/2
                        else (candidate_1 + candidate_2) / 2
                   end)
        end) as loom
from (select t.*,
             max(case when seqnum = floor(cnt / 2) then x end) over () as candidate_1,
             max(case when seqnum = floor(cnt / 2) + 1 then x end) over () as candidate_2,
             max(case when seqnum = floor(cnt / 2) + 2 then x end) over () as candidate_3
      from (select t.*,
                   row_number() over (order by x) as seqnum,
                   count(*) over () as cnt
            from t
           ) t
     ) t
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...