2016-08-26 9 views
1

Контекст:MySql найти медиану столбца сгруппированных по другому, а не медианы для всей колонки

Я пытаюсь принять ряд рыночных сделок, а также определить сумму денег, фактически движущееся в тип вещи. Это в значительной степени моя первая попытка MySql, поэтому запрос некрасиво, но следующий почти работает:

SELECT types.typename, 
     averages.type, 
     averages.price, 
     movement.sold, 
     (averages.price * movement.sold) AS value 
FROM (SELECT type, 
       Round(Avg(price)) AS price 
     FROM orders 
     GROUP BY type) AS averages 
     INNER JOIN (SELECT type, 
          (startingvolume - currentvolume) AS sold 
        FROM (SELECT type, 
            Sum(volume)  AS currentVolume, 
            Sum(volumeentered) startingVolume 
          FROM orders 
          GROUP BY type) AS movement 
        WHERE (startingvolume - currentvolume) > 10000 
        ORDER BY sold) AS movement 
       ON averages.type = movement.type 
     INNER JOIN invtypes AS types 
       ON types.typeid = averages.type 
ORDER BY value DESC 
LIMIT 10 ; 

-

+------------------------------------+-------+---------+------------+------------------+ 
| typeName       | type | price | sold  | value   | 
+------------------------------------+-------+---------+------------+------------------+ 
| Dirt        | 34 | 1904767 | 2670581874 | 5086836224393358 | 
| Light Wood       | 2629 | 42999 | 2756595 |  118530828405 | 
| Dark Wood       | 24509 | 47344 | 1107771 |  52446310224 | 
| Stone        | 21922 | 18386 | 1505884 |  27687183224 | 
| Grass        | 238 | 5643 | 4554470 |  25700874210 | 
| Paper        | 3814 | 25635 |  861006 |  22071888810 | 
| Iron        | 3699 | 320270 |  58833 |  18842444910 | 
| Ink        | 16275 | 8552 | 2200545 |  18819060840 | 
| Loam        | 2679 | 5759 | 2608771 |  15023912189 | 
| Copper        | 672 | 904612 |  14989 |  13559229268 | 
+------------------------------------+-------+---------+------------+------------------+ 

Проблема с указанными выше данными является то, что исходные данные рынка неизбежно испорчен выбросами, как вы можете увидеть ниже:

select type, price from orders where type = 34 order by price desc limit 10; 

-

+------+-----------+ 
| type | price  | 
+------+-----------+ 
| 34 | 200000000 | 
| 34 |  15.99 | 
| 34 |  12.06 | 
| 34 |  10 | 
| 34 |  7.67 | 
| 34 |  7.5 | 
| 34 |  7.3 | 
| 34 |  7.17 | 
| 34 |  7.1 | 
| 34 |  7.06 | 
+------+-----------+ 

Основная проблема:

99% рынок данных является чистой, но выпадающими уничтожить средний и MySql, кажется, не имеет среднюю функцию. Я нашел несколько примеров того, как найти медиану всего столбца, но мне нужен медианный элемент.

Как определить медианную для каждого элемента вместо среднего значения элемента или эффективно очистить данные этих выбросов до запуска первичного запроса?

Примечание: Я пробовал исключать результаты через std, но цены на товары варьируются от $ 17 до $ 10B, в то время как отклонение остается относительно низким, независимо от ценового диапазона.

ответ

0

Я не буду касаться вашего исходного запроса, потому что он очень сложный, но один из вариантов, который вы могли бы сделать, - использовать подзапрос, чтобы удалить статистические выбросы. Например, если вы хотите, чтобы удалить любой выброс из orders таблицы, значение которого больше, чем говорят два стандартных отклонения от среднего значения можно использовать:

SELECT t1.type, 
     t1.price 
FROM orders t1 
INNER JOIN 
(
    SELECT type, 
      AVG(price) AS AVG, 
      STD(price) AS STD 
    FROM orders 
    GROUP BY type 
) t2 
    ON t1.type = t2.type 
WHERE t1.price < ABS(2*t2.STD - t2.AVG) -- any value more than 2 standard devations 
             -- away from the mean is discarded 

Demo здесь:

SQLFiddle

+0

Хорошая идея, но, как упоминалось в первоначальном сообщении, соотношение отклонения к цене крайне несовместимо между дешевыми и дорогостоящими товарами, в результате чего любой множитель аннулирует все заказы заданного диапазона цен. –

+0

Я не следую вашей логике. Затем просто измените пороговое значение для отбрасывания выбросов. Ваши данные никоим образом не являются особенностью AFAIK. Основываясь на данных примера, которые вы предоставили, выбросы _way_ за пределами первого стандартного отклонения. –