2013-04-02 26 views

risposta

20

Diciamo che la mediana è l'elemento nel mezzo di una lista ordinata.

SQLite (4 o 3) non ha alcuna funzione built-in per questo, ma è possibile farlo a mano:

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

Quando v'è un numero pari di record, è comune definire la mediana come la media dei due record centrali. In questo caso, la media può essere calcolata in questo modo:

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

combinando i pari e dispari casi poi risultati in questo:

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

Questa è una soluzione piacevole, ma sembra essere difficile da utilizzare se si desidera calcolare la mediana di un risultato "gruppo per" anziché dell'intera tabella. Considera "seleziona grp, min (val), median (val), max (val) dal gruppo di tabelle per grp". –

+0

@Acer - Vedo che hai ragione. In questo caso non ho un'elegante soluzione a singola istruzione senza supporto database per MEDIAN. Ciò che ti viene in mente è questo: 1) Crea una tabella usando la clausola group by e SELECT INTO (chiama questa tabella "G"), in forma ordinata, e aggiungi una colonna AUTOINCREMENT (chiamala colonna "i"). 2) Crea una query che calcola il (max (G.i) + min (G.i))/2.0 per ciascun gruppo (chiama questa colonna 'x'). 3) Utilizzando la tabella Pick, selezionare le voci da G dove ABS (G.i-Pick.x) <1. Se prendi la media da quell'ultima tabella, avrai la risposta per ogni gruppo. Non carino. –

11

C'è un pacchetto estensione delle varie funzioni matematiche per sqlite3. Include funzioni di gruppo come la mediana.

Sarà più lavoro ottenere questo risultato rispetto alla risposta di CL, ma potrebbe essere utile se pensate di aver bisogno di una qualsiasi delle altre funzioni.

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

(Here è la guida per come compilare e le estensioni del carico SQLite.)

Dalla descrizione:

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 2015/04/12: Fixing "simbolo indefinito: sin "

Come è stato menzionato nei commenti, questa estensione potrebbe non funzionare correttamente nonostante una compilazione riuscita.

Ad esempio, la compilazione può funzionare e su Linux è possibile copiare il file .so risultante in /usr/local/lib. Ma .load /usr/local/lib/libsqlitefunctions dal sqlite3 shell può quindi generare questo errore:

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

compilazione in questo modo sembra funzionare:

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

e copiando il file .so a /usr/local/lib mostra nessun errore simile:

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

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

Non sono sicuro del motivo per cui l'ordine delle opzioni per gcc è importante in questo caso particolare, ma a quanto pare d OES.

Credito per notare questo va a Ludvick Lidicky 's commento sulla this blog post

+0

Qualche idea su come installarlo? Il file stesso non aiuta molto. – jameshfisher

+0

@jameshfisher Prova a chiedercelo in un'altra domanda, ecco un vantaggio. Per curiosità, ho provato a compilare le estensioni stasera. Seguire le istruzioni incluse nei commenti C nella parte superiore del file era abbastanza semplice (hai letto il file e trovato quelli, giusto?) Ma ci sono alcuni bug. Si compila con gcc su Ubuntu 14.04 LTS, con prerequisito "libsqlite3-dev", risultante in una lib condivisa "libsqlitefunctions.so". Lo stesso sqlite3 di Ubuntu prova a caricarlo quando viene dato il comando SELECT load_extension ('./ libsqlitefunctions') ma genera un errore "simbolo indefinito: sinh". – Paul

+1

Questo è stato molto più facile da configurare di quanto mi aspettassi. Ben fatto! –

0

SELECT AVG (x) restituisce solo l'anno dei valori di data formattati come AAAA-MM-DD, così ho ottimizzato la soluzione di CL solo leggermente per accogliere date:

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) 
); 
Problemi correlati