2012-01-18 12 views
5

Desidero scrivere una funzione che calcoli un semplice calcolo medio ritagliato in MySQL. La funzione sarà (ovviamente) una funzione aggregata. Sono nuovo a scrivere funzioni ecc in MySQL quindi potrebbe fare con qualche aiuto.Calcolo medio ridotto in MySQL

L'algoritmo della media troncata sarà il seguente (pseudocodice):

CREATE AGGREGATE FUNCTION trimmed_mean(elements DOUBLE[], trim_size INTEGER) 
RETURNS DOUBLE 
BEGIN 
    -- determine number of elements 
    -- ensure that number of elements is greater than 2 * trim_size else return error 
    -- order elements in ASC order 
    -- chop off smallest trim_size elements and largest trim_size elements 
    -- calculate arithmetic average of the remaining elements 
    -- return arithmetic average 
END 

Chiunque può aiutare con il modo di scrivere la funzione di cui sopra in modo corretto, per l'uso con MySQL?

+2

Esiste un motivo specifico per cui vuoi farlo come una funzione piuttosto che come una query? Inoltre, dato che hai preferito una risposta a una domanda precedente perché usava l'SQL standard, dovresti essere in grado di usarlo su più RDBMS diversi (cioè non solo su MySQL)? –

+0

@MarkBannister intendevo lavorare con PG (il mio db preferito!), Ma ho dovuto saltare troppi cerchi per far funzionare il PG con PHP (ricompilando PHP [o simili pazzi peti] ecc., Quindi ho optato per mySQL che Ho già lavorato con PHP. Il motivo per cui l'ho voluto come funzione è che voglio restituire una media ritagliata come una colonna in una query. Suppongo (se avessi una soluzione SQL), potrei hackerare alcuni SQL per "incollare" i valori medi ritagliati come una colonna al mio set di dati restituito. –

+0

@MarkBannister: risposta breve alla tua domanda. Una versione ANSI SQL sarebbe l'ideale. Ma dal momento che sto lavorando con mySQL, quindi se devo essere db-centric, un SQL con SQL MySQL avrà la precedenza. –

risposta

1

Questo è un compito facile, è necessario scrivere in C/C++ ...


Un'opzione all'interno di MySQL per sé, è quello di scrivere una funzione di visualizzazione o scalare che aggrega i dati come vuoi, ma da una tabella specifica. Ciò limita ovviamente la funzione a una singola tabella di origine, che potrebbe non essere l'ideale.

Un modo per aggirare questo potrebbe essere quella di avere un tavolo dedicato a questa funzione ...

  • avviare una transazione
  • chiara tabella
  • inserire i vostri dati di esempio
  • query vista/funzione

(O qualcosa di simile)

Questo preclude le variazioni GROUP BY, a meno che non si utilizzino parametri SQL o pass dinamici per la funzione per specifici modelli di raggruppamento.

È tutto meno che ideale, mi dispiace.

+0

Non mi dispiace andare giù per il percorso C/C++ (come l'ultima risorsa) - ma preferirei di no, semplicemente perché non voglio passare ore a familiarizzare con i tipi di dati interni mySQL ecc. Se c'è un esempio di "ciao mondo" per un aggregato scritto in C/C++, che sarebbe un ottimo punto di partenza (nel ridurre la curva di apprendimento), dal momento che quello che voglio fare è relativamente banale (la parte dell'algoritmo che è). –

+0

Nel collegamento da Dems: * "La distribuzione di origine MySQL include un file sql/udf_example.c che definisce 5 nuove funzioni." * –

1

Date un'occhiata a questo esempio (per MySQL) -

Crea tabella di prova:

CREATE TABLE test_table (
    id INT(11) NOT NULL AUTO_INCREMENT, 
    value INT(11) DEFAULT NULL, 
    PRIMARY KEY (id) 
); 

INSERT INTO test_table(value) VALUES 
    (10), (2), (3), (5), (4), (7), (1), (9), (3), (5), (9); 

Diamo calcolare il valore medio (a cura variante):

SET @trim_size = 3; 

SELECT AVG(value) avg FROM (
    SELECT value, @pos:[email protected] + 1 pos FROM (SELECT * FROM test_table ORDER BY value) t1, (SELECT @pos:=0) t2 
) t 
WHERE pos > @trim_size AND pos <= @pos - @trim_size; 

+--------+ 
| avg | 
+--------+ 
| 4.8000 | 
+--------+ 
+0

Sicuramente dovrebbe essere 4.8 - il trim dovrebbe eliminare uno ma non entrambi i 3? cioè: (non (1 + 2 + 3) + 3 + 4 + 5 + 5 + 7 + non (9 + 9 + 10))/5 –

+0

@ Mark Bannister Hai ragione. Ho perso il punto - ordinare gli elementi in ordine ASC. Dovrebbe essere ordinato dal campo 'valore'. Ho modificato la query. Grazie;-) – Devart