Расчет медианы с Mysql - PullRequest
       38

Расчет медианы с Mysql

7 голосов
/ 23 марта 2011

У меня проблемы с вычислением медианы списка значений, а не среднего.

Я нашел эту статью Простой способ вычисления медианы с MySQL

У него есть ссылка на следующий запрос, который я не правильно понимаю.

ВЫБРАТЬ x.val из данных x, данных y GROUP BY x.val ИМЕЯ СУММУ (ЗНАК (1-ЗНАК (y.val-x.val))) = (СЧЕТ (*) + 1) / 2

Если у меня есть столбец времени, и я хочу вычислить среднее значение, на что ссылаются столбцы x и y?

Ответы [ 5 ]

10 голосов
/ 31 мая 2011

Я предлагаю более быстрый способ.

Получите количество строк:

SELECT CEIL(COUNT(*)/2) FROM data;

Затем возьмите среднее значение в отсортированном подзапросе:

SELECT max(val) FROM (SELECT val FROM data ORDER BY val limit @middlevalue) x;

Я проверил это с набором случайных чисел 5x10e6, и он найдет медиану менее чем за 10 секунд.

Это найдет произвольный процентиль, заменив COUNT(*)/2 наCOUNT(*)*n, где n - процентиль (.5 для медианы, .75 для 75-го процентиля и т. Д.).

2 голосов
/ 23 марта 2011

val - ваш столбец времени, x и y - две ссылки на таблицу данных (вы можете написать data AS x, data AS y).

РЕДАКТИРОВАТЬ: чтобы избежать вычисления ваших сумм дважды, выможет хранить промежуточные результаты.

CREATE TEMPORARY TABLE average_user_total_time 
      (SELECT SUM(time) AS time_taken 
            FROM scores 
            WHERE created_at >= '2010-10-10' 
                    and created_at <= '2010-11-11' 
            GROUP BY user_id);

Затем вы можете вычислить медиану для этих значений, которые находятся в именованной таблице.

РЕДАКТИРОВАТЬ: временная таблица не будет работать Вот.Вы можете попробовать использовать обычную таблицу с типом таблицы "MEMORY".Или просто укажите свой подзапрос, который дважды вычисляет значения для медианы в вашем запросе.Кроме этого, я не вижу другого решения.Это не значит, что нет лучшего способа, может быть, кто-то придет с идеей.

1 голос
/ 03 декабря 2014

Поиск медианы в mysql с помощью group_concat

Запрос:

SELECT
    IF(count%2=1,
       SUBSTRING_INDEX(substring_index(data_str,",",pos),",",-1),
       (SUBSTRING_INDEX(substring_index(data_str,",",pos),",",-1) 
         + SUBSTRING_INDEX(substring_index(data_str,",",pos+1),",",-1))/2) 
    as median 
FROM (SELECT group_concat(val order by val) data_str,
      CEILING(count(*)/2) pos,
      count(*) as count from data)temp;

Пояснение:

Сортировка выполняется по порядку внутри функции group_concat

Позиция (pos) и Общее количество элементов (count) определены. CEILING для определения позиции помогает нам использовать функцию substring_index в следующих шагах.

На основании количества определяется четное или нечетное количество значений.

  • Нечетные значения: напрямую выберите элемент, принадлежащий к позиции, используя substring_index.
  • Четные значения: найдите элемент, принадлежащий pos и pos + 1, затем сложите их и разделите на 2, чтобы получить медиану.

Наконец, вычисляется медиана.

1 голос
/ 23 марта 2011

Сначала попытайтесь понять, что такое медиана: это среднее значение в отсортированном списке значений.

Как только вы это поймете, подход состоит из двух шагов:

  1. сортировка значений в любом порядке
  2. выберите среднее значение (если не нечётное количество значений, выберите среднее значение из двух средних значений)

Пример:

Median of 0 1 3 7 9 10: 5 (because (7+3)/2=5)
Median of 0 1 3 7 9 10 11: 7 (because 7 is the middle value)

Итак, для сортировки дат вам нужно числовое значение; Вы можете получить их метку времени (в секундах, прошедших с начала эпохи) и использовать определение медианы.

0 голосов
/ 25 ноября 2015

Если у вас есть таблица R со столбцом с именем A, и вы хотите медиану для A , вы можете сделать следующее:

SELECT A FROM R R1
WHERE ( SELECT COUNT(A) FROM R R2 WHERE R2.A < R1.A ) = ( SELECT COUNT(A) FROM R R3 WHERE R3.A > R1.A )

Примечание : Это будет работать только в том случае, если в А. нет дублированных значений. Также нулевые значения не допускаются.

...