SQL: Условное среднее на основе групп

#sql #oracle

Вопрос:

Предположим, у меня есть такие данные

 GROUP ID     VALUE 
---------- ---------- 
        1       4 
        1       7 
        1       2 
        1       3 
        1       5 
        2       8 
        2       6
        2       3 
        2       6
        2       1 
        3       7 
        3       6 
        3       2 
        3       1 
 

Я хочу рассчитать среднее ЗНАЧЕНИЕ по идентификатору группы, но при условии, что ЗНАЧЕНИЕ меньше или равно медиане по группе.

Так, например, для группы 1 медиана равна 4, а 2,3,4 меньше или равны 4, поэтому она должна давать для группы 1:

 GROUP ID     COND AVG 
---------- ---------- 
        1       4 
...
 

Кто-нибудь имеет представление, как я могу сделать это в Oracle/SQL?

Ответ №1:

Вы можете вычислить медиану как аналитическую функцию, а затем агрегировать:

 select group_id,
       avg(case when value < value_median then value end) as avg_below_median
from (select t.*,
             median(value) over (partition by group_id) as value_median
      from t
     ) t
group by group_id;
 

Примечание. Вы также можете фильтровать, используя where предложение:

 select group_id, avg(value) as avg_below_median
from (select t.*,
             median(value) over (partition by group_id) as value_median
      from t
     ) t
where value < value_median
group by group_id;
 

Но первый метод упрощает добавление других выражений.