Was ist der einfachste (und hoffentlich nicht zu langsame) Weg, um den Median mit MySQL zu berechnen? Ich habe AVG(x)
den Mittelwert ermittelt, aber es fällt mir schwer, einen einfachen Weg zur Berechnung des Medians zu finden. Im Moment kehre ich alle Zeilen zu PHP zurück, sortiere sie und wähle dann die mittlere Zeile aus, aber es muss sicherlich eine einfache Möglichkeit geben, dies in einer einzelnen MySQL-Abfrage zu tun.
Beispieldaten:
id | val
--------
1 4
2 7
3 2
4 2
5 9
6 8
7 3
Das Sortieren nach val
gibt 2 2 3 4 7 8 9
, also sollte der Median sein 4
, gegenüber SELECT AVG(val)
dem == 5
.
sql
mysql
statistics
median
davr
quelle
quelle
Antworten:
In MariaDB / MySQL:
Steve Cohen weist darauf hin, dass @rownum nach dem ersten Durchgang die Gesamtzahl der Zeilen enthält. Dies kann verwendet werden, um den Median zu bestimmen, sodass kein zweiter Durchgang oder Join erforderlich ist.
Außerdem
AVG(dd.val)
unddd.row_number IN(...)
wird verwendet, um einen Median korrekt zu erzeugen, wenn eine gerade Anzahl von Datensätzen vorhanden ist. Argumentation:Schließlich enthält MariaDB 10.3.3+ eine MEDIAN-Funktion
quelle
WHERE 1
in,WHERE d.val IS NOT NULL
so dassNULL
Zeilen ausgeschlossen werden, um diese Methode mit der nativeAVG
select avg(value) from (select value, row_number from (select a - b as value from a_table join b_table order by value))
Ich habe gerade eine andere Antwort online in den Kommentaren gefunden :
Stellen Sie sicher, dass Ihre Spalten gut indiziert sind und der Index zum Filtern und Sortieren verwendet wird. Überprüfen Sie mit den EXPLAIN-Plänen.
Berechnen Sie die "mittlere" Zeilennummer. Vielleicht verwenden :
median_row = floor(count / 2)
.Dann wählen Sie es aus der Liste:
Dies sollte Ihnen eine Zeile mit nur dem gewünschten Wert zurückgeben.
Jacob
quelle
Ich habe festgestellt, dass die akzeptierte Lösung bei meiner MySQL-Installation nicht funktioniert hat und einen leeren Satz zurückgegeben hat. Diese Abfrage hat jedoch in allen Situationen funktioniert, in denen ich sie getestet habe:
quelle
data
und wird mit zwei Namen verwendet,x
undy
.Leider liefern weder die Antworten von TheJacobTaylor noch von velcrow genaue Ergebnisse für aktuelle Versionen von MySQL.
Die Antwort von Velcro von oben ist nah, wird jedoch für Ergebnismengen mit einer geraden Anzahl von Zeilen nicht korrekt berechnet. Mediane sind entweder definiert als 1) die mittlere Zahl bei ungeraden Sätzen oder 2) der Durchschnitt der beiden mittleren Zahlen bei geraden Sätzen.
Hier ist die Lösung für Klettverschlüsse, die sowohl für ungerade als auch für gerade Zahlenmengen geeignet ist:
Befolgen Sie dazu die folgenden 3 einfachen Schritte:
quelle
Ich schlage einen schnelleren Weg vor.
Holen Sie sich die Zeilenanzahl:
SELECT CEIL(COUNT(*)/2) FROM data;
Nehmen Sie dann den Mittelwert in einer sortierten Unterabfrage:
SELECT max(val) FROM (SELECT val FROM data ORDER BY val limit @middlevalue) x;
Ich habe dies mit einem 5x10e6-Datensatz von Zufallszahlen getestet und er wird den Median in weniger als 10 Sekunden finden.
quelle
Ein Kommentar auf dieser Seite in der MySQL-Dokumentation enthält den folgenden Vorschlag:
quelle
Installieren und verwenden Sie diese statistischen MySQL-Funktionen: http://www.xarg.org/2012/07/statistical-functions-in-mysql/
Danach ist es einfach, den Median zu berechnen:
quelle
Die meisten der oben genannten Lösungen funktionieren nur für ein Feld der Tabelle. Möglicherweise müssen Sie den Median (50. Perzentil) für viele Felder in der Abfrage ermitteln.
Ich benutze das:
Sie können die "50" im obigen Beispiel durch ein beliebiges Perzentil ersetzen, was sehr effizient ist.
Stellen Sie einfach sicher, dass Sie genügend Speicher für die GROUP_CONCAT haben. Sie können dies ändern mit:
Weitere Details: http://web.performancerasta.com/metrics-tips-calculating-95th-99th-or-any-percentile-with-single-mysql-query/
quelle
Ich habe diesen folgenden Code, den ich auf HackerRank gefunden habe, und er ist ziemlich einfach und funktioniert in jedem Fall.
quelle
Aufbauend auf der Antwort des Klettverschlusses für diejenigen unter Ihnen, die einen Median aus etwas machen müssen, das nach einem anderen Parameter gruppiert ist:
quelle
Sie könnten die benutzerdefinierte Funktion verwenden , die gefunden werden hier .
quelle
Kümmert sich um eine ungerade Wertzählung - gibt in diesem Fall den Durchschnitt der beiden Werte in der Mitte an.
quelle
Mein Code, effizient ohne Tabellen oder zusätzliche Variablen:
quelle
GROUP_CONCAT
es auf 1023 Zeichen beschränkt ist, selbst wenn es in einer anderen Funktion wie dieser verwendet wird.Optional können Sie dies auch in einer gespeicherten Prozedur tun:
quelle
x IS NOT NULL
soll hinzugefügt werden?CALL median("table","x","x IS NOT NULL")
.Meine unten vorgestellte Lösung funktioniert in nur einer Abfrage, ohne dass eine Tabelle, eine Variable oder sogar eine Unterabfrage erstellt wird. Außerdem können Sie den Median für jede Gruppe in gruppenweisen Abfragen abrufen (dies ist das, was ich brauchte!):
Es funktioniert aufgrund einer intelligenten Verwendung von group_concat und substring_index.
Um jedoch big group_concat zuzulassen, müssen Sie group_concat_max_len auf einen höheren Wert setzen (standardmäßig 1024 Zeichen). Sie können es so einstellen (für die aktuelle SQL-Sitzung):
Weitere Informationen zu group_concat_max_len: https://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_group_concat_max_len
quelle
Ein weiteres Riff zu Velcrows Antwort, verwendet jedoch eine einzelne Zwischentabelle und nutzt die für die Zeilennummerierung verwendete Variable, um die Anzahl zu ermitteln, anstatt eine zusätzliche Abfrage zur Berechnung durchzuführen. Startet auch die Zählung, sodass die erste Zeile Zeile 0 ist, damit Sie mit Floor and Ceil einfach die mittleren Zeilen auswählen können.
quelle
Das obige scheint für mich zu funktionieren.
quelle
{98,102,102,98}
ist beispielsweise,100
aber Ihr Code gibt an102
. Bei ungeraden Zahlen hat es gut funktioniert.Ich habe einen Zwei-Abfrage-Ansatz verwendet:
Diese sind in eine Funktion defn eingeschlossen, sodass alle Werte von einem Aufruf zurückgegeben werden können.
Wenn Ihre Bereiche statisch sind und sich Ihre Daten nicht häufig ändern, ist es möglicherweise effizienter, diese Werte vorab zu berechnen / zu speichern und die gespeicherten Werte zu verwenden, anstatt jedes Mal von Grund auf neu abzufragen.
quelle
Da ich nur eine Median- UND Perzentillösung benötigte, habe ich basierend auf den Ergebnissen in diesem Thread eine einfache und recht flexible Funktion erstellt. Ich weiß, dass ich selbst glücklich bin, wenn ich "Readymade" -Funktionen finde, die sich leicht in meine Projekte integrieren lassen. Deshalb habe ich beschlossen, schnell Folgendes zu teilen:
Die Verwendung ist sehr einfach, Beispiel aus meinem aktuellen Projekt:
quelle
Hier ist mein Weg. Natürlich könnte man es in eine Prozedur setzen :-)
Sie könnten die Variable vermeiden
@median_counter
, wenn Sie sie unterteilen:quelle
Dieser Weg scheint sowohl gerade als auch ungerade Zählungen ohne Unterabfrage einzuschließen.
quelle
Basierend auf der Antwort von @ bob wird die Abfrage so verallgemeinert, dass mehrere Mediane zurückgegeben werden können, die nach bestimmten Kriterien gruppiert sind.
Denken Sie beispielsweise an den mittleren Verkaufspreis für Gebrauchtwagen auf einem Autoparkplatz, gruppiert nach Jahr und Monat.
quelle
Oft müssen wir den Median nicht nur für die gesamte Tabelle berechnen, sondern auch für Aggregate in Bezug auf unsere ID. Mit anderen Worten, berechnen Sie den Median für jede ID in unserer Tabelle, wobei jede ID viele Datensätze enthält. (Gute Leistung und funktioniert in vielen SQL + behebt das Problem von Geraden und Gewinnchancen, mehr über die Leistung verschiedener Median-Methoden https://sqlperformance.com/2012/08/t-sql-queries/median )
Ich hoffe es hilft
quelle
MySQL unterstützt seit Version 8.0 Fensterfunktionen, die Sie verwenden können
ROW_NUMBER
oderDENSE_RANK
( NICHT verwenden,RANK
da es denselben Werten denselben Rang zuweist wie im Sportranking):quelle
Wenn MySQL ROW_NUMBER hat, lautet der MEDIAN (lassen Sie sich von dieser SQL Server-Abfrage inspirieren):
Das IN wird verwendet, wenn Sie eine gerade Anzahl von Einträgen haben.
Wenn Sie den Median pro Gruppe ermitteln möchten, klicken Sie in Ihren OVER-Klauseln einfach auf PARTITION BY-Gruppe.
rauben
quelle
ROW_NUMBER OVER
, keine TEILUNG DURCH, nichts davon; Dies ist MySql, keine echte DB-Engine wie PostgreSQL, IBM DB2, MS SQL Server usw. ;-).Nachdem ich alle vorherigen gelesen hatte, stimmten sie nicht mit meiner tatsächlichen Anforderung überein, also implementierte ich meine eigene, die keine Prozedur oder komplizierten Anweisungen benötigt, sondern nur
GROUP_CONCAT
alle Werte aus der Spalte, in der ich den MEDIAN erhalten und einen COUNT DIV BY anwenden wollte 2 Ich extrahiere den Wert aus der Mitte der Liste wie bei der folgenden Abfrage:(POS ist der Name der Spalte, deren Median ich erhalten möchte)
Ich hoffe, dass dies für jemanden nützlich sein könnte, so wie viele andere Kommentare von dieser Website für mich waren.
quelle
Wenn Sie die genaue Zeilenanzahl kennen, können Sie diese Abfrage verwenden:
Wo
<half> = ceiling(<size> / 2.0) - 1
quelle
Ich habe eine Datenbank mit ungefähr 1 Milliarde Zeilen, die wir benötigen, um das Durchschnittsalter in der Menge zu bestimmen. Das Sortieren einer Milliarde Zeilen ist schwierig. Wenn Sie jedoch die verschiedenen Werte aggregieren, die gefunden werden können (Alter zwischen 0 und 100), können Sie DIESE Liste sortieren und mit arithmetischer Magie ein beliebiges Perzentil wie folgt finden:
Diese Abfrage hängt von Ihren db-unterstützenden Fensterfunktionen ab (einschließlich ROWS UNBOUNDED PRECEDING). Wenn Sie dies jedoch nicht tun, ist es einfach, aggData CTE mit sich selbst zu verbinden und alle vorherigen Summen in der Spalte 'akkumuliert' zusammenzufassen, anhand derer ermittelt wird, welche Wert enthält das angegebene Präzentil. Die obige Stichprobe berechnet p10, p25, p50 (Median), p75 und p90.
-Chris
quelle
Entnommen aus: http://mdb-blog.blogspot.com/2015/06/mysql-find-median-nth-element-without.html
Ich würde einen anderen Weg vorschlagen, ohne zu verbinden , aber mit Strings zu arbeiten
Ich habe es nicht mit Tabellen mit großen Daten überprüft, aber kleine / mittlere Tabellen funktioniert einwandfrei.
Das Gute dabei ist, dass es auch durch GROUPING funktioniert, sodass der Median für mehrere Elemente zurückgegeben werden kann.
Hier ist der Testcode für die Testtabelle:
und den Code zum Finden des Medians für jede Gruppe:
Ausgabe:
quelle
In einigen Fällen wird der Median wie folgt berechnet:
Der "Median" ist der "mittlere" Wert in der Liste der Zahlen, wenn sie nach Wert geordnet sind. Bei geraden Zählsätzen ist der Median der Durchschnitt der beiden Mittelwerte . Ich habe dafür einen einfachen Code erstellt:
Der zurückgegebene $ -Median wäre das erforderliche Ergebnis :-)
quelle