2013-04-02 9 views

Odpowiedz

20

Załóżmy, że mediana jest elementem w środku uporządkowanej listy.

SQLite (4 lub 3) nie ma żadnego wbudowanego w funkcję, ale jest to możliwe, aby to zrobić ręcznie:

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

Gdy jest parzysta liczba rekordów, to Często definiuje się medianę jako średnią z dwóch środkowych rekordów. W tym przypadku średnia może być obliczana następująco:

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

Połączenie parzystych i nieparzystych przypadki następnie Skutkuje to:

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

Jest to dobre rozwiązanie, ale wydaje się trudne w użyciu, jeśli chcemy obliczyć medianę wyniku "grupa po" zamiast całej tabeli. Rozważ "wybierz grp, min (val), medianę (val), max (val) z grupy table przez grp". –

+0

@Acer - Widzę, że masz rację. W tym przypadku nie mam eleganckiego, pojedynczego rozwiązania instrukcji bez obsługi baz danych dla MEDIAN. To, co przychodzi na myśl, to: 1) Utwórz tabelę za pomocą klauzuli group by i SELECT INTO (wywołaj tę tabelę "G") w posortowanej formie i dodaj kolumnę AUTOINCREMENT (nazwij ją kolumną "i"). 2) Utwórz zapytanie, które oblicza (max (G.i) + min (G.i))/2.0 dla każdej grupy (wywołaj tę kolumnę "x"). 3) Używając tabeli Wybierz, wybierz wpisy z G, gdzie ABS (G.i-Pick.x) <1. Jeśli weźmiesz średnią z tego ostatniego stołu, otrzymasz odpowiedź dla każdej grupy. Nie ładne. –

11

Jest paczka rozbudowa różnych funkcji matematycznych dla sqlite3. Obejmuje funkcje grupowe, takie jak mediana.

Będzie to wymagało więcej pracy niż odpowiedzi CL, ale może się opłacać, jeśli uważasz, że będziesz potrzebować którejś z pozostałych funkcji.

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

(Here jest przewodnikiem jak skompilować i rozszerzenia SQLite obciążenie).

Z opisu:

Provide mathematical and string extension functions for SQL queries using the loadable extensions mechanism. Math: acos, asin, atan, atn2, atan2, acosh, asinh, atanh, difference, degrees, radians, 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. Aggregate: stdev, variance, mode, median, lower_quartile, upper_quartile.

UPDATE 12.04.2015: fixing „niezdefiniowany symbol: sinh "

Jak wspomniano w komentarzach, to rozszerzenie może nie działać poprawnie pomimo pomyślnej kompilacji.

Na przykład kompilowanie może działać, a w systemie Linux można skopiować wynikowy plik .so do /usr/local/lib. Ale .load /usr/local/lib/libsqlitefunctions z powłoki sqlite3 może następnie wygenerować ten błąd:

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

kompilowanie go w ten sposób wydaje się działać:

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

i kopiowanie pliku do /usr/local/lib.so nie wykazuje podobny błąd:

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

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

Nie jestem pewien, dlaczego kolejność opcji do gcc ma znaczenie w tym konkretnym przypadku, ale najwyraźniej d oes.

Kredyt dla zauważając to idzie do Ludvick Lidicky „s komentarzu this blog post

+0

Każdy pomysł, jak to zainstalować? Sam plik niewiele pomaga. – jameshfisher

+0

@jameshfisher Spróbuj zapytać o to w innym pytaniu, oto początek. Z ciekawości próbowałem dzisiaj kompilować rozszerzenia. Postępowanie zgodnie z instrukcjami zawartymi w komentarzach C na górze pliku było dość proste (przeczytałeś plik i znalazłeś je, prawda?), Ale są pewne błędy. Kompiluje się z gcc na Ubuntu 14.04 LTS, z warunkiem wstępnym "libsqlite3-dev", czego wynikiem jest udostępniona lib "libsqlitefunctions.so". Ten sam system operacyjny Ubuntu sqlite3 próbuje załadować go, gdy otrzyma polecenie SELECT load_extension ("./ libsqlitefunctions"), ale zgłasza błąd "niezdefiniowany symbol: sinh". – Paul

+1

To było łatwiejsze do skonfigurowania, niż się spodziewałem. Dobra droga! –

0

SELECT AVG (x) zwraca tylko rok od wartości dat sformatowanych jako YYYY-MM-DD, więc manipulowane rozwiązanie CL jest tylko nieznacznie, aby pomieścić daty:

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) 
); 
Powiązane problemy