Я хотел бы вычислить медианное значение в числовой строке. Как это сделать в SQLite 4?
Скажем, что медиана - это элемент в середине упорядоченного списка.
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))
Для 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.
Как уже упоминалось в комментариях, это расширение может работать неправильно, несмотря на успешную компиляцию.
Например, компиляция может работать, и в 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 комментарий это сообщение в блоге
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)
);