Гость
Форумы / Oracle [игнор отключен] [закрыт для гостей] / подсчет среднего без отклонений / 13 сообщений из 13, страница 1 из 1
25.10.2015, 22:58
    #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
25.10.2015, 23:30
    #39086265
andreymx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет среднего без отклонений
а где в твоём примере 5%?
...
Рейтинг: 0 / 0
26.10.2015, 01:06
    #39086296
losaped
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет среднего без отклонений
andreymxа где в твоём примере 5%?
nu мне хотя бы со строками разоюраться)
...
Рейтинг: 0 / 0
26.10.2015, 07:30
    #39086337
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет среднего без отклонений
losapedсреднее время нахождения документа в подтипе и при этом не учитывать 5% самых долгих и самых коротких документовРанжируешь, фильтруешь, усредняешь. Никакой высшей атематики. Но методом тыка не выйдет.
...
Рейтинг: 0 / 0
26.10.2015, 07:56
    #39086347
andreymx
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет среднего без отклонений
в реальной жизни вопросов будет много

что делать, если самых долгих/коротких документов - 6%?
а если документов всего 2?
...
Рейтинг: 0 / 0
26.10.2015, 08:52
    #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
26.10.2015, 08:57
    #39086375
Elic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет среднего без отклонений
mcureenabсортируешь по убыванию, убираешь первые строки, потом по возрастанию и снова убираешь первые строки.Сортировать-то два раза зачем?
...
Рейтинг: 0 / 0
26.10.2015, 09:31
    #39086395
mcureenab
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет среднего без отклонений
Elicmcureenabсортируешь по убыванию, убираешь первые строки, потом по возрастанию и снова убираешь первые строки.Сортировать-то два раза зачем?
думается, автору надо отбросить 5% и 5% от количества записей, а не от времени ожидания.
...
Рейтинг: 0 / 0
26.10.2015, 10:16
    #39086458
гипотет
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет среднего без отклонений
select avg(max(x))
from t
group by rownum
having rownum/nullif(count(*),0) between 0.05 and 0.95;
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
05.04.2019, 15:42
    #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
05.04.2019, 15:57
    #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
05.04.2019, 16:37
    #39797434
Alex_SPD
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
подсчет среднего без отклонений
123йй, действительно. Но у меня диапазоны типа 2-3 тысячи, говорю же - частное решение.
Можно все закинуть в arr_float_type() и написать алгоритмическую сортировку, мне побыстрее хотелось. )

В общем можно под себя дорабатывать.
...
Рейтинг: 0 / 0
05.04.2019, 18:02
    #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
Форумы / Oracle [игнор отключен] [закрыт для гостей] / подсчет среднего без отклонений / 13 сообщений из 13, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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