2012-01-18 8 views
5

Chcę napisać funkcję, która oblicza proste obcinane średnie obliczenia w MySQL. Funkcja (oczywiście) będzie funkcją agregującą. Jestem nowy w pisaniu funkcji itp. W MySQL, więc mógłbym zrobić trochę pomocy.Przycięte średnie obliczenie w MySQL

Algorytm średnia obcięta będzie wyglądał następująco (Pseudokod):

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 

może ktoś pomóc z tym, jak napisać funkcję powyżej poprawnie, do użytku z MySQL?

+2

Czy istnieje konkretny powód, dla którego chcesz to zrobić jako funkcję, a nie jako zapytanie? Ponadto, biorąc pod uwagę, że wolisz odpowiedź na poprzednie pytanie, ponieważ korzystał on ze standardowego kodu SQL, czy będziesz w stanie używać go w wielu różnych RDBMS (tj. Nie tylko w MySQL)? –

+0

@MarkBannister Miałem zamiar pracować z PG (mój ulubiony db!), Ale musiałem przeskoczyć przez zbyt wiele kółek, aby PG mógł pracować z PHP (ponowna kompilacja PHP [lub podobnym zwariowanym pytaniem] itd.), Więc wybrałem mySQL, który Mam już pracę z PHP. Powodem, dla którego chciałem to jako funkcja, jest to, że chcę zwrócić średnią obciętą jako kolumnę w zapytaniu. Przypuszczam (gdybym miał rozwiązanie SQL), mógłbym zhakować razem jakiś SQL, by "wkleić" skrócone wartości średnie jako kolumnę do mojego zwróconego zestawu danych. –

+0

@MarkBannister: krótka odpowiedź na twoje pytanie. Wersja ANSI SQL byłaby idealna. Ponieważ jednak pracuję z mySQL, to jeśli mam __have__ na db-centric, pierwszeństwo ma SQL z MySQL. –

Odpowiedz

1

To nie małe zadanie, trzeba zapisać go w C/C++ ...


opcja w samym MySQL jest napisać funkcję widoku lub skalarne który agreguje dane, jak chcesz, ale z konkretnej tabeli. To oczywiście ogranicza funkcję do tabeli z jednym źródłem, co może nie być idealne.

sposób wokół to może być na stolik poświęconą tej funkcji ...

  • rozpocząć transakcję
  • jasne tabeli
  • wstawić dane przykładowe
  • zapytania Widok/funkcja

(Lub coś podobnego)

Wyklucza to warianty GROUP BY, chyba że do funkcji użyto dynamicznych parametrów sql lub pass dla określonych wzorców grupowania.

Wszystko jest mniej niż idealne, przepraszam.

+0

Nie mam nic przeciwko zejściu z C/C++ (jako w ostateczności) - ale wolałbym nie, po prostu dlatego, że nie chcę spędzać godzin na zapoznawaniu się z wewnętrznymi typami danych MySQL itp. Jeśli istnieje przykład "cześć świata" dla agregatu napisanego w C/C++, to byłby bardzo dobrym punktem wyjścia (w zmniejszaniu krzywej uczenia się), ponieważ to, co chcę zrobić, jest względnie banalne (część z algorytmem). –

+0

W łączu z Dems: * "Dystrybucja źródeł MySQL zawiera plik sql/udf_example.c, który definiuje 5 nowych funkcji." * –

1

Wystarczy popatrzeć na ten przykład (MySQL) -

Tworzenie tabeli testowej:

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

Policzmy wartość średnia (edytowany wariant):

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

Z pewnością powinno być 4,8 - przycięcie powinno wyeliminować jedną, ale nie obie z 3s? tj: (nie (1 + 2 + 3) + 3 + 4 + 5 + 5 + 7 + nie (9 + 9 + 10))/5 –

+0

@ Mark Bannister Masz rację. Brakowało mi punktów - elementów porządku w porządku ASC. Powinien być uporządkowany według pola 'value'. Edytowałem zapytanie. Dzięki;-) – Devart