Wie finde ich den Medianwert einer Spalte in MySQL?

10

Ich kann mir das nur mit zwei Datenbankabfragen vorstellen. Der erste findet die Anzahl der Zeilen in der Datenbank und der zweite wählt mit einem ORDER BYin der Spalte, die mich interessiert, und LIMIT X, 1wobei X die Hälfte der Anzahl der Zeilen ist.

Gibt es eine einfache Möglichkeit, dies mit nur einer Abfrage zu tun?

Im Moment verwende ich Durchschnittswerte in meinen Berechnungen, aber ich denke, der Mittelwert wäre besser. Es gibt keine Obergrenze für die Werte und sie werden von unten durch 0 begrenzt.


EDIT: Ja, ich wollte "Median" sagen, hatte aber einen Gehirnfehler und suchte nach "Mittelwert". Ich habe jetzt die Antwort bei stackoverflow gefunden

JIStone
quelle
Nach einigem Lesen metascheint es eine Spaltung zu geben, ob diese Frage hier oder bei SO gestellt werden sollte. Ich erkenne, dass dies möglicherweise keine Abfrage auf Ninja-Ebene ist , aber ich bin ratlos und es gibt keinen DBA in der Firma, für die ich arbeite (insgesamt 6 Personen).
JIStone

Antworten:

6

Es gibt ziemlich viel Diskussion hier auf Medianwerte aus einer MySQL - Tabelle zu berechnen. Suchen Sie einfach auf der Seite nach "Median".

Abgesehen davon fällt mir auf, dass es dafür keine eingebaute Funktion gibt. Der Median beschreibt häufig eher die zentrale Tendenz als den Mittelwert. Access / VBA hat die gleiche Lücke in seiner Funktionsliste.

Snubian
quelle
Genau. Bei der Bearbeitung einer großen Abfrage machen die zusätzlichen Zeilen das Ganze nur umständlicher und schwieriger zu debuggen / zu warten.
JIStone
2

Ich habe nirgendwo eine Lösung gesehen, die es schafft, den Median in einer einzigen Abfrage zu erhalten. Ich habe nichts gegen temporäre Tabellen, aber wenn sie nicht notwendig sind, großartig! Folgendes habe ich mir ausgedacht:

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;

Ich habe dies für einen gleichmäßigen Satz getestet und die richtige Antwort erhalten. brand_prof besteht nur aus zwei Spalten: brand_name und profit, ein Dezimalwert. Wenn dies ganzzahlige Werte wären, müssten Sie möglicherweise "Decke ((CAST COUNT (*) AS DECIMAL) ..." mehr als ich getestet habe. Die coole Idee, ein kartesisches Produkt zu verwenden und die Summe der Zeichen in Beziehung zu setzen, war nicht meins. Ich habe den Autor leider vergessen.

Jeff Humphreys
quelle