Das Folgende ist das einfachste mögliche Beispiel, obwohl jede Lösung in der Lage sein sollte, auf so viele n Top-Ergebnisse zu skalieren, die benötigt werden:
Wie würden Sie bei einer folgenden Tabelle mit Spalten für Personen, Gruppen und Alter die beiden ältesten Personen in jeder Gruppe ermitteln? (Bindungen innerhalb von Gruppen sollten nicht zu mehr Ergebnissen führen, sondern die ersten 2 in alphabetischer Reihenfolge)
+ -------- + ------- + ----- + | Person | Gruppe | Alter | + -------- + ------- + ----- + | Bob | 1 | 32 | | Jill | 1 | 34 | | Shawn | 1 | 42 | | Jake | 2 | 29 | | Paul | 2 | 36 | | Laura | 2 | 39 | + -------- + ------- + ----- +
Gewünschte Ergebnismenge:
+ -------- + ------- + ----- + | Shawn | 1 | 42 | | Jill | 1 | 34 | | Laura | 2 | 39 | | Paul | 2 | 36 | + -------- + ------- + ----- +
ANMERKUNG: Diese Frage baut auf einer früheren Frage auf: Abrufen von Datensätzen mit maximalem Wert für jede Gruppe gruppierter SQL-Ergebnisse - zum Abrufen einer einzelnen oberen Zeile aus jeder Gruppe, die von @Bohemian eine hervorragende MySQL-spezifische Antwort erhalten hat:
select *
from (select * from mytable order by `Group`, Age desc, Person) x
group by `Group`
Würde gerne in der Lage sein, dies auszubauen, obwohl ich nicht sehe, wie.
Antworten:
Hier ist eine Möglichkeit, dies mit
UNION ALL
(siehe SQL Fiddle with Demo ) zu tun . Dies funktioniert mit zwei Gruppen. Wenn Sie mehr als zwei Gruppen haben, müssen Sie diegroup
Anzahl angeben und Abfragen für jede hinzufügengroup
:Es gibt verschiedene Möglichkeiten, dies zu tun. In diesem Artikel finden Sie die beste Route für Ihre Situation:
http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
Bearbeiten:
Dies funktioniert möglicherweise auch für Sie. Es wird eine Zeilennummer für jeden Datensatz generiert. Wenn Sie ein Beispiel aus dem obigen Link verwenden, werden nur die Datensätze mit einer Zeilennummer von weniger als oder gleich 2 zurückgegeben:
Siehe Demo
quelle
SELECT
(und bewertet sie manchmal sogar nicht in der richtigen Reihenfolge). Der Schlüssel zur Lösung besteht darin, alle Variablenzuweisungen in einem einzigen Ausdruck zusammenzufassen. Hier ist ein Beispiel: stackoverflow.com/questions/38535020/… .In anderen Datenbanken können Sie dies mit verwenden
ROW_NUMBER
. MySQL wird nicht unterstützt,ROW_NUMBER
aber Sie können Variablen verwenden, um es zu emulieren:Sehen Sie, wie es online funktioniert: sqlfiddle
Bearbeiten Ich habe gerade bemerkt, dass bluefeet eine sehr ähnliche Antwort gepostet hat: +1 für ihn. Diese Antwort hat jedoch zwei kleine Vorteile:
Also lasse ich es hier, falls es jemandem helfen kann.
quelle
JOIN (SELECT @prev := NULL, @rn := 0) AS vars
. Ich habe die Idee, leere Variablen zu deklarieren, aber es scheint für MySql irrelevant.Versuche dies:
DEMO
quelle
a.person
.Wie wäre es mit Self-Joining:
gibt mir:
Die Antwort von Bill Karwin, Top 10-Datensätze für jede Kategorie auszuwählen, hat mich stark inspiriert
Ich verwende auch SQLite, aber dies sollte unter MySQL funktionieren.
Eine andere Sache: Oben habe ich die
group
Spalte der Einfachheit halber durch einegroupname
Spalte ersetzt.Bearbeiten :
Nach dem Kommentar des OP zu fehlenden Gleichstandsergebnissen erhöhte ich die Antwort von Snuffin, um alle Gleichstände anzuzeigen. Dies bedeutet, dass, wenn die letzten Bindungen sind, mehr als 2 Zeilen zurückgegeben werden können, wie unten gezeigt:
gibt mir:
quelle
ERROR 1242 (21000): Subquery returns more than 1 row
vermutlich wegen derGROUP BY
. Wenn ich dieSELECT MIN
Unterabfrage alleine ausführe , werden drei Zeilen generiert:34, 39, 112
und dort scheint der zweite Wert 36 zu sein, nicht 39.Die Ausführung der Snuffin-Lösung scheint ziemlich langsam zu sein, wenn Sie viele Zeilen haben und die Lösungen von Mark Byers / Rick James und Bluefeet in meiner Umgebung (MySQL 5.6) nicht funktionieren, da die Reihenfolge nach der Ausführung von select angewendet wird. Hier ist also eine Variante von Marc Byers / Rick James-Lösungen zur Behebung dieses Problems (mit einer zusätzlichen Auswahl):
Ich habe eine ähnliche Abfrage für eine Tabelle mit 5 Millionen Zeilen versucht und das Ergebnis wird in weniger als 3 Sekunden zurückgegeben
quelle
LIMIT 9999999
zu jeder abgeleiteten Tabelle mit einem hinzuORDER BY
. Dies kann verhindern, dass dasORDER BY
ignoriert wird.Überprüfen Sie dies heraus:
SQL Fiddle: http://sqlfiddle.com/#!2/cdbb6/15
quelle
max(internal_version - 1)
- also weniger Stress :)Wenn die anderen Antworten nicht schnell genug sind Probieren Sie diesen Code aus :
Ausgabe:
quelle
Ich wollte dies teilen, weil ich lange nach einer einfachen Möglichkeit gesucht habe, dies in einem Java-Programm zu implementieren, an dem ich arbeite. Dies gibt nicht ganz die Ausgabe, die Sie suchen, aber es ist nah. Die aufgerufene Funktion in MySQL
GROUP_CONCAT()
funktionierte sehr gut, um anzugeben, wie viele Ergebnisse in jeder Gruppe zurückgegeben werden sollen. Die VerwendungLIMIT
oder eine der anderen ausgefallenen Methoden, um dies zu versuchen, hat beiCOUNT
mir nicht funktioniert. Wenn Sie also bereit sind, eine modifizierte Ausgabe zu akzeptieren, ist dies eine großartige Lösung. Nehmen wir an, ich habe eine Tabelle mit dem Namen "Student" mit Studentenausweisen, Geschlecht und gpa. Nehmen wir an, ich möchte 5 gpas für jedes Geschlecht erreichen. Dann kann ich die Abfrage so schreibenBeachten Sie, dass der Parameter '5' angibt, wie viele Einträge in jeder Zeile verkettet werden sollen
Und die Ausgabe würde ungefähr so aussehen
Sie können die
ORDER BY
Variable auch ändern und anders anordnen. Wenn ich also das Alter des Schülers hätte, könnte ich das 'gpa desc' durch 'age desc' ersetzen und es wird funktionieren! Sie können der Gruppe auch Variablen per Anweisung hinzufügen, um mehr Spalten in der Ausgabe zu erhalten. Dies ist nur ein Weg, den ich gefunden habe, der ziemlich flexibel ist und gut funktioniert, wenn Sie nur Ergebnisse auflisten können.quelle
In SQL Server
row_numer()
ist eine leistungsstarke Funktion, die wie folgt leicht zu Ergebnissen führen kannquelle
Bei MySQL gibt es eine wirklich gute Antwort auf dieses Problem - So erhalten Sie die besten N Zeilen pro Gruppe
Basierend auf der Lösung im Link, auf den verwiesen wird, lautet Ihre Anfrage wie folgt:
Wo
n
ist dastop n
undyour_table
ist der Name Ihrer Tabelle.Ich denke, die Erklärung in der Referenz ist wirklich klar. Zum schnellen Nachschlagen werde ich es hier kopieren und einfügen:
quelle