Как я могу рассчитать медиану значений в SQLite?

14

Я хотел бы вычислить медианное значение в числовой строке. Как это сделать в SQLite 4?

Теги:
median

3 ответа

20
Лучший ответ

Скажем, что медиана - это элемент в середине упорядоченного списка.

SQLite (4 или 3) для этого не имеет встроенной функции, но это можно сделать вручную:

SELECT x
FROM MyTable
ORDER BY x
LIMIT 1
OFFSET (SELECT COUNT(*)
        FROM MyTable) / 2

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

SELECT AVG(x)
FROM (SELECT x
      FROM MyTable
      ORDER BY x
      LIMIT 2
      OFFSET (SELECT (COUNT(*) - 1) / 2
              FROM MyTable))

Сочетание нечетных и четных случаев приводит к следующему:

SELECT AVG(x)
FROM (SELECT x
      FROM MyTable
      ORDER BY x
      LIMIT 2 - (SELECT COUNT(*) FROM MyTable) % 2    -- odd 1, even 2
      OFFSET (SELECT (COUNT(*) - 1) / 2
              FROM MyTable))
  • 4
    Это хорошее решение, но его трудно использовать, если вы хотите вычислить медиану результата «group by» вместо всей таблицы. Рассмотрим "выберите grp, min (val), медиану (val), max (val) из группы таблиц по grp".
  • 0
    @Acer Acer - Я вижу, что ты прав. В этом случае у меня нет элегантного решения с одним оператором без поддержки базы данных для MEDIAN. На ум приходит следующее: 1) Создайте таблицу, используя предложение group by и SELECT INTO (назовите эту таблицу «G»), в отсортированной форме, и добавьте столбец AUTOINCREMENT (назовите его столбцом «i»). 2) Создайте запрос, который вычисляет (max (Gi) + min (Gi)) / 2.0 для каждой группы (назовите этот столбец «x»). 3) Используя таблицу Pick, выберите записи из G, где ABS (Gi-Pick.x) <1. Если вы возьмете среднее из этой последней таблицы, у вас будет свой ответ для каждой группы. Не красиво
Показать ещё 1 комментарий
11

Для sqlite3 существует набор расширений различных математических функций. Он включает в себя функции группы, такие как медиана.

Будет больше работать над этим, чем CL, но может быть целесообразным, если вы считаете, что вам понадобятся какие-либо другие функции.

http://www.sqlite.org/contrib/download/extension-functions.c?get=25

(Здесь описано, как компилировать и загружать расширения SQLite.)

Из описания:

Предоставление математических и строковых функций расширения для SQL-запросов с использованием механизма загружаемых расширений. Математика: acos, asin, atan, atn2, atan2, acosh, asinh, atanh, разница, градусы, радианы, cos, sin, tan, cot, cosh, sinh, tanh, coth, exp, log, log10, power, sign, sqrt, square, ceil, floor, pi. String: replicate, charindex, leftstr, rightstr, ltrim, rtrim, trim, replace, reverse, proper, padl, padr, padc, strfilter. Совокупность: stdev, дисперсия, режим, медиана, lower_quartile, upper_quartile.

ОБНОВЛЕНИЕ 2015-04-12: Фиксация "undefined symbol: sinh"

Как уже упоминалось в комментариях, это расширение может работать неправильно, несмотря на успешную компиляцию.

Например, компиляция может работать, и в Linux вы можете скопировать полученный .so файл в /usr/local/lib. Но .load /usr/local/lib/libsqlitefunctions из оболочки sqlite3 может затем сгенерировать эту ошибку:

Error: /usr/local/lib/libsqlitefunctions.so: undefined symbol: sinh

Скомпилировать его таким образом, кажется, работает:

gcc -fPIC -shared extension-functions.c -o libsqlitefunctions.so -lm

И копирование файла .so на /usr/local/lib не показывает аналогичной ошибки:

sqlite> .load /usr/local/lib/libsqlitefunctions

sqlite> select cos(pi()/4.0);
---> 0.707106781186548

Я не уверен, почему порядок опций gcc имеет значение в данном конкретном случае, но, по-видимому, это так.

Кредит за это замечает Ludvick Lidicky комментарий это сообщение в блоге

  • 0
    Есть идеи, как это установить? Сам файл мало помогает.
  • 0
    @jameshfisher Попробуйте спросить об этом в другом вопросе. Из любопытства я попытался скомпилировать расширения сегодня вечером. Следовать инструкциям, включенным в комментарии C в верхней части файла, было достаточно просто (вы прочитали файл и нашли его, верно?), Но есть некоторые ошибки. Он компилируется с gcc в Ubuntu 14.04 LTS с обязательным условием "libsqlite3-dev", в результате чего создается общая библиотека "libsqlitefunctions.so". Sqlite3 того же Ubuntu пытается загрузить его, когда ему дана команда SELECT load_extension ('./ libsqlitefunctions'), но выдает ошибку "undefined symbol: sinh".
Показать ещё 3 комментария
0

SELECT AVG (x) возвращает только данные даты года, отформатированные как YYYY-MM-DD, поэтому я немного изменил решение CL для размещения дат:

SELECT DATE(JULIANDAY(MIN(MyDate)) + (JULIANDAY(MAX(MyDate)) - JULIANDAY(MIN(MyDate)))/2) as Median_Date
FROM (
   SELECT MyDate
      FROM MyTable
      ORDER BY MyDate
      LIMIT 2 - ((SELECT COUNT(*) FROM MyTable) % 2) -- odd 1, even 2
      OFFSET (SELECT (COUNT(*) - 1) / 2 FROM MyTable)
);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню