Как рассчитать среднюю цену за единицу, используя PERCENTILE_CONT и идентификатор GROUP BY - PullRequest
0 голосов
/ 12 января 2019

Я использую Postgres 9,5 и пытаюсь вычислить Медиана и Средняя цена за единицу с GROUP BY идентификатор . Вот запрос в DBFIDDLE

Вот данные

id   | price | units
-----+-------+--------
1    |  100  | 15
1    |  90   | 10
1    |  50   |  8
1    |  40   |  8
1    |  30   |  7
2    |  110  | 22
2    |  60   |  8
2    |  50   | 11

Используя percentile_cont, это мой запрос:

SELECT id,
  ceil(avg(price)) as avg_price,
  percentile_cont(0.5) within group (order by price) as median_price,
  ceil( sum (price) / sum (units) ) AS avg_pp_unit,
  ceil( percentile_cont(0.5) within group (order by price)  / 
        percentile_cont(0.5) within group (order by units) ) as median_pp_unit
FROM t
GROUP by id

Этот запрос возвращает:

id| avg_price | median_price | avg_pp_unit  | median_pp_unit 
--+-----------+--------------+--------------+---------------
1 |   62      |     50       |      6       |      7 
2 |   74      |     60       |      5       |      5

Я почти уверен, что среднее вычисление верно. Правильный ли это способ расчета средней цены за единицу ?

Этот пост предполагает, что это правильно (хотя производительность плохая), но мне любопытно, может ли деление в вычислении медианы исказить результат.

Вычисление медианы с PERCENTILE_CONT и группировка

1 Ответ

0 голосов
/ 12 января 2019

Медиана - это значение, отделяющее верхнюю половину от нижней половины выборки данных (совокупность или распределение вероятностей). Для набора данных его можно рассматривать как «среднее» значение. https://en.wikipedia.org/wiki/Median

Итак, ваша средняя цена составляет 55, а средние единицы - 9

        Sort by price                  Sort by units
  id    |   price   |  units |  | id    |  price  |   units  
 -------|-----------|--------|  |-------|---------|---------- 
      1 | 30        |      7 |  |     1 |      30 | 7        
      1 | 40        |      8 |  |     1 |      40 | 8        
      1 | 50        |      8 |  |     1 |      50 | 8        
 >>>  2 | 50        |     11 |  |     2 |      60 | 8    <<<<    
 >>>  2 | 60        |      8 |  |     1 |      90 | 10   <<<<
      1 | 90        |     10 |  |     2 |      50 | 11       
      1 | 100       |     15 |  |     1 |     100 | 15       
      2 | 110       |     22 |  |     2 |     110 | 22       
        |           |        |  |       |         |          
         (50+60)/2                               (8+10)/2 
          55                                        9        

Я не уверен, что вы намереваетесь за «среднюю цену за единицу»:

CREATE TABLE t(
   id    INTEGER  NOT NULL
  ,price INTEGER  NOT NULL
  ,units INTEGER  NOT NULL
);
INSERT INTO t(id,price,units) VALUES (1,30,7);
INSERT INTO t(id,price,units) VALUES (1,40,8);
INSERT INTO t(id,price,units) VALUES (1,50,8);
INSERT INTO t(id,price,units) VALUES (2,50,11);
INSERT INTO t(id,price,units) VALUES (2,60,8);
INSERT INTO t(id,price,units) VALUES (1,90,10);
INSERT INTO t(id,price,units) VALUES (1,100,15);
INSERT INTO t(id,price,units) VALUES (2,110,22);

SELECT
       percentile_cont(0.5) WITHIN GROUP (ORDER BY price) med_price
     , percentile_cont(0.5) WITHIN GROUP (ORDER BY units) med_units
FROM
  t;

     | med_price | med_units 
 ----|-----------|----------- 
   1 |        55 |         9 

Если столбец «цена» представляет «цену за единицу», то вам не нужно делить 55 на 9, но если «цена» - это «общая сумма заказа», то вам придется делить на единицы: 55/9 = 6,11

...