Jak znaleźć wartość mediany kolumny w MySQL?

10

Mogę sobie tylko wyobrazić, że robię to z dwoma zapytaniami do bazy danych. Pierwszy znajduje liczbę wierszy w bazie danych, a drugi wybiera z ORDER BYkolumną, która mnie interesuje i LIMIT X, 1gdzie X jest połową liczby wierszy.

Czy istnieje prosty sposób, aby to zrobić za pomocą tylko jednego zapytania?

W tej chwili używam średnich w moich obliczeniach, ale myślę, że średnia byłaby lepsza; wartości nie mają górnej granicy i są one ograniczone od dołu przez 0.


EDYCJA: tak, chciałem powiedzieć „mediana”, ale miałem jakiś błąd mózgu i szukałem „średniej”. Znalazłem teraz odpowiedź w stackoverflow

JIStone
źródło
Po lekkim przeczytaniu metawydaje się, że istnieje podział co do pogody, to pytanie powinno być tutaj lub w SO. Rozumiem, że to może nie być zapytanie na poziomie ninja , ale mnie zaskoczyło i w firmie, w której pracuję, nie ma DBA (łącznie 6 osób).
JIStone

Odpowiedzi:

6

Jest sporo dyskusji tutaj na obliczanie wartości mediany z tabeli MySQL. Wystarczy wyszukać na stronie „mediana”.

Nawiasem mówiąc, wydaje mi się, że nie mam wbudowanej funkcji, aby to zrobić. Mediana jest często bardziej opisowa niż tendencja centralna. Access / VBA ma ten sam otwór na liście funkcji.

Snubian
źródło
Zgadzam się. Po przetworzeniu w duże zapytanie dodatkowe wiersze sprawiają, że cała sprawa jest bardziej kłopotliwa i trudna do debugowania / utrzymania.
JIStone
2

Nigdzie nie widziałem rozwiązania, które zdołałoby uzyskać medianę w jednym zapytaniu. Nie przeszkadza mi tabele tymczasowe, ale jeśli nie są konieczne, świetnie! Oto, co wymyśliłem:

SELECT AVG(profit) median, nofitems FROM(
  SELECT x.profit, SUM(SIGN(1.0-SIGN(y.profit-x.profit))) diff, count(*) nofitems, floor(count(*)+1/2)
  FROM brand_prof x, brand_prof y
  GROUP BY x.profit
  HAVING SUM(SIGN(1.0-SIGN(y.profit-x.profit))) = floor((COUNT(*)+1)/2)
      OR SUM(SIGN(1.0-SIGN(y.profit-x.profit))) = ceiling((COUNT(*)+1)/2)
) x;

Przetestowałem to na parzysty zestaw i uzyskałem właściwą odpowiedź. brand_prof to tylko dwie kolumny: nazwa marki i zysk, wartość dziesiętna. Jeśli byłyby to liczby całkowite, być może trzeba rzucić „sufit ((CAST COUNT (*) AS DECIMAL) ...”) Więcej niż testowałem. Fajnym pomysłem na użycie produktu kartezjańskiego i powiązanie sumy znaków było nie moje. Niestety nie pamiętam autora.

Jeff Humphreys
źródło