2012-01-18 36 views
5

Quiero escribir una función que calcula un cálculo simple de medias recortadas en MySQL. La función será (obviamente) una función agregada. Soy nuevo en la escritura de funciones, etc. en MySQL, así que podría hacerlo con algo de ayuda.Cálculo de medias recortadas en MySQL

El algoritmo de la media recortada será el siguiente (pseudocódigo):

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 

¿Alguien puede ayudar con la forma de escribir correctamente la función anterior, para su uso con MySQL?

+2

¿Hay una razón específica por la que desea hacer esto como una función, en lugar de como una consulta? Además, dado que prefirió una respuesta a una pregunta anterior porque usó SQL estándar, ¿tendrá que ser capaz de utilizar esto en varios RDBMS diferentes (es decir, no solo MySQL)? –

+0

@MarkBannister ¡Tenía la intención de trabajar con PG (mi DB preferido!), Pero tuve que saltar demasiados aros para hacer que PG trabajara con PHP (recompilando PHP [o locos similares)], así que opté por mySQL, que Ya tengo trabajo con PHP. La razón por la que lo quería como una función es que quiero devolver una media recortada como una columna en una consulta. Supongo (si tuviera una solución SQL), podría hackear juntos algunos SQL para 'pegar' los valores medios recortados como una columna en mi conjunto de datos devuelto. –

+0

@MarkBannister: respuesta breve a su pregunta. Una versión ANSI SQL sería ideal. Pero dado que estoy trabajando con mySQL, entonces si tengo __have__ ser db-céntrico, un SQL con sabor MySQL tendrá prioridad. –

Respuesta

1

Eso no es tarea fácil, es necesario escribirlo en C/C++ ...


una opción dentro de sí MySQL, es escribir una vista o función escalar que agrega los datos como lo desea, pero desde una tabla específica. Obviamente, esto restringe la función a una única tabla fuente, que puede no ser ideal.

Una forma de evitar esto podría ser tener una mesa dedicada a esta función ...

  • iniciar una transacción
  • clara la tabla
  • insertar sus datos de ejemplo
  • consulta la ver/función

(O algo similar)

Esto excluye las variaciones GROUP BY, a menos que use parámetros sql dinámicos o pase a su función para patrones de agrupamiento específicos.

Todo es menos que ideal, lo siento.

+0

No me importa bajar la ruta C/C++ (como un último recurso), pero preferiría no hacerlo, simplemente porque no quiero pasar horas familiarizándome con los tipos de datos internos mySQL, etc. Si hay un ejemplo de 'hello world' para un agregado escrito en C/C++, eso sería un muy buen punto de partida (para reducir la curva de aprendizaje), ya que lo que quiero hacer es relativamente trivial (la parte del algoritmo que es). –

+0

En el enlace de Dems: * "La distribución fuente de MySQL incluye un archivo sql/udf_example.c que define 5 nuevas funciones." * –

1

Tener un vistazo a este ejemplo (para MySQL) -

Crear tabla de prueba:

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

vamos a calcular el valor promedio (variante editado):

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

Seguramente debería ser 4.8 - ¿el recorte debería eliminar uno pero no ambos? es decir: (no (1 + 2 + 3) + 3 + 4 + 5 + 5 + 7 + no (9 + 9 + 10))/5 –

+0

@Mark Bannister Tienes razón. Me he perdido el punto - ordenar elementos en orden ASC. Debe ordenarse por el campo 'valor'. He editado la consulta. Gracias;-) – Devart

Cuestiones relacionadas