powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / подсчет среднего без отклонений
13 сообщений из 13, страница 1 из 1
подсчет среднего без отклонений
    #39086237
losaped
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Подскажите как посчитать в oracle среднее без отклонений, например, мне нужно посчитать среднее время нахождения документа в подтипе и при этом не учитывать 5% самых долгих и самых коротких документов

пробовал:
Код: sql
1.
avg(doc_quantity) OVER (PARTITION BY SUBTYPE_ID ORDER BY HOUR_SUBTYPE ROWS between 5 FOLLOWING AnD 5 PRECEDING)



это я пытаюсь убрать первые и последние 5 строк, но не получается
...
Рейтинг: 0 / 0
подсчет среднего без отклонений
    #39086265
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а где в твоём примере 5%?
...
Рейтинг: 0 / 0
подсчет среднего без отклонений
    #39086296
losaped
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andreymxа где в твоём примере 5%?
nu мне хотя бы со строками разоюраться)
...
Рейтинг: 0 / 0
подсчет среднего без отклонений
    #39086337
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
losapedсреднее время нахождения документа в подтипе и при этом не учитывать 5% самых долгих и самых коротких документовРанжируешь, фильтруешь, усредняешь. Никакой высшей атематики. Но методом тыка не выйдет.
...
Рейтинг: 0 / 0
подсчет среднего без отклонений
    #39086347
andreymx
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
в реальной жизни вопросов будет много

что делать, если самых долгих/коротких документов - 6%?
а если документов всего 2?
...
Рейтинг: 0 / 0
подсчет среднего без отклонений
    #39086373
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
losapedПодскажите как посчитать в oracle среднее без отклонений, например, мне нужно посчитать среднее время нахождения документа в подтипе и при этом не учитывать 5% самых долгих и самых коротких документов

пробовал:
Код: sql
1.
avg(doc_quantity) OVER (PARTITION BY SUBTYPE_ID ORDER BY HOUR_SUBTYPE ROWS between 5 FOLLOWING AnD 5 PRECEDING)



это я пытаюсь убрать первые и последние 5 строк, но не получается

FOLLOWING ... PRECEDING ведут отсчет от текущей позиции, а не от начала "окна". а тебе от начала нужно сколько то отсчитать и от конца. сортируешь по убыванию, убираешь первые строки, потом по возрастанию и снова убираешь первые строки.
...
Рейтинг: 0 / 0
подсчет среднего без отклонений
    #39086375
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mcureenabсортируешь по убыванию, убираешь первые строки, потом по возрастанию и снова убираешь первые строки.Сортировать-то два раза зачем?
...
Рейтинг: 0 / 0
подсчет среднего без отклонений
    #39086395
mcureenab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Elicmcureenabсортируешь по убыванию, убираешь первые строки, потом по возрастанию и снова убираешь первые строки.Сортировать-то два раза зачем?
думается, автору надо отбросить 5% и 5% от количества записей, а не от времени ожидания.
...
Рейтинг: 0 / 0
подсчет среднего без отклонений
    #39086458
гипотет
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
select avg(max(x))
from t
group by rownum
having rownum/nullif(count(*),0) between 0.05 and 0.95;
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
подсчет среднего без отклонений
    #39797358
Alex_SPD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет!
Искал такую же штуку, но чтобы можно было бы группировать.

В итоге пришлось разбираться с пользовательскими агрегатными функциями. Привожу код, для тех кто так же поиском сюда выйдет.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
-- создаем тип в котором будем копить значения
CREATE OR REPLACE TYPE arr_float_type is table of float;

--это костыль, чтобы обойти ограничение на один параметр в агрегатной функции.
CREATE OR REPLACE TYPE avg_timur_param AS VARRAY (3) OF float;

--собственно объект с функцией
CREATE OR REPLACE TYPE t_avg_timur AS OBJECT
(
    --type arr_type is table of varchar2(64) index by binary_integer;
    arr  arr_float_type,
    lower_limit float,
    upper_limit float,  
            
    STATIC FUNCTION ODCIAggregateInitialize(
        sctx IN OUT t_avg_timur) RETURN NUMBER,
        
    MEMBER FUNCTION ODCIAggregateIterate(
        self IN OUT t_avg_timur,
        val IN avg_timur_param) RETURN NUMBER,
        
    MEMBER FUNCTION ODCIAggregateMerge(
        self IN OUT t_avg_timur,
        ctx2 IN t_avg_timur) RETURN NUMBER,
        
    MEMBER FUNCTION ODCIAggregateTerminate(
        self IN OUT t_avg_timur,
        returnvalue OUT float,
        flags IN NUMBER) RETURN NUMBER
        

        
)

\
CREATE OR REPLACE TYPE BODY t_avg_timur IS
    STATIC FUNCTION ODCIAggregateInitialize(
        sctx IN OUT t_avg_timur) RETURN NUMBER
    IS
    BEGIN
        sctx := t_avg_timur(arr_float_type(),0,100);
        RETURN ODCIConst.Success;        
    END ODCIAggregateInitialize;

    MEMBER FUNCTION ODCIAggregateIterate(
        self IN OUT t_avg_timur,
        val IN avg_timur_param) RETURN NUMBER
    IS
    BEGIN
        if val(1) is not null then  --пустые не берем
            self.arr.extend(1);
            self.arr(arr.count):=val(1);
        end if;
        self.lower_limit:=val(2);
        self.upper_limit:=val(3);
        RETURN ODCIConst.Success;
    END ODCIAggregateIterate;

    MEMBER FUNCTION ODCIAggregateMerge(
        self IN OUT t_avg_timur,
        ctx2 IN t_avg_timur) RETURN NUMBER
    IS
    BEGIN
        RETURN ODCIConst.Success;
    END ODCIAggregateMerge;

    MEMBER FUNCTION ODCIAggregateTerminate(
        self IN OUT t_avg_timur,
        returnvalue OUT float,
        flags IN NUMBER) RETURN NUMBER
    IS
      tmp sys.OdciNumberList := sys.OdciNumberList();
      prc arr_float_type;
      i number;
      res_sum number :=0;
      res_cnt number:=0;      
    BEGIN
       --сортируем массив 
          tmp.extend(self.arr.count);
          prc:=arr_float_type();
          prc.extend(self.arr.count);
          
          for j in 1..self.arr.count loop
            tmp(j) := self.arr(j);
            prc(j):=j/self.arr.count;
          end loop;
          select  *
            bulk  collect
            into  self.arr
            from  table(tmp)
          order by column_value;

          for j in 1..self.arr.count loop
            if (prc(j)>=self.lower_limit/100 and prc(j)<=self.upper_limit/100) then --считаем только то, что в середине
               res_cnt:=res_cnt+1;
               res_sum:=res_sum+self.arr(j);
            end if;  
          end loop;
        
        if  res_cnt=0 then  
          returnvalue:=null;
        else   
          returnvalue := res_sum/res_cnt;
        end if;  
        
        RETURN ODCIConst.Success;
    END ODCIAggregateTerminate;
END;

-- функция которую будем юзать в запросе
CREATE OR REPLACE FUNCTION avg_timur(val avg_timur_param) RETURN float
     AGGREGATE USING t_avg_timur;



Использовать примерно так:
где val - это столбец по которому считаем, попадут значения между 25 и 75 процентами. Т.е. отсекаем по 25%.
Код: plsql
1.
2.
3.
select name,  avg_timur(avg_timur_param(val,25,75))
from test
group by name





На универсальность не претендует, создано для конкретной задачи.
Если данных мало, то работать будет плохо. Например если в наборе 2 значения - первая строка будет считаться 50%, вторая 100%.
Но думаю смысл понятен, можно дорабатывать под себя.
...
Рейтинг: 0 / 0
подсчет среднего без отклонений
    #39797388
123йй
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alex_SPDЕсли данных мало, то работать будет плохо.
да и если много, то не очень
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
Connected to Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 
SQL> select text from all_source where owner='SYS' and name = 'ODCINUMBERLIST'
  2   order by line;
TEXT
--------------------------------------------------------------------------------
TYPE ODCINumberList AS VARRAY(32767) of NUMBER

SQL> 
...
Рейтинг: 0 / 0
подсчет среднего без отклонений
    #39797434
Alex_SPD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
123йй, действительно. Но у меня диапазоны типа 2-3 тысячи, говорю же - частное решение.
Можно все закинуть в arr_float_type() и написать алгоритмическую сортировку, мне побыстрее хотелось. )

В общем можно под себя дорабатывать.
...
Рейтинг: 0 / 0
подсчет среднего без отклонений
    #39797488
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
with t as (select mod(rownum,2) g, rownum val from dual connect by level <= 100)
select g, avg(val) val_avg, count(val) val_cnt 
from (
        select t.*
             , percent_rank() over(partition by g order by val) val_rnk
             , row_number() over(partition by g order by val) 
             / count(*) over(partition by g) row_rnk
        from t)
--where val_rnk between .05 and .95 -- Отбрасываем крайние значения
where row_rnk between .05 and .95 -- Отбрасываем крайние строки
group by g
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / подсчет среднего без отклонений
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]