Wählen Sie einen Wert aus einer Gruppe aus, basierend auf der Reihenfolge in anderen Spalten

Problem

Angenommen, ich habe diesen Tischtab (Geige verfügbar).

| g | a | b |     v |
---------------------
| 1 | 3 | 5 |   foo |
| 1 | 4 | 7 |   bar |
| 1 | 2 | 9 |   baz |
| 2 | 1 | 1 |   dog |
| 2 | 5 | 2 |   cat |
| 2 | 5 | 3 | horse |
| 2 | 3 | 8 |   pig |

Ich gruppiere Zeilen nachg, und für jede Gruppe möchte ich einen Wert aus der Spaltev. Ich will es aber nichtirgendein Wert, aber ich möchte den Wert aus der Zeile mit maximalaund von all diesen die mit dem Maximumb. Mit anderen Worten, mein Ergebnis sollte sein

| 1 |   bar |
| 2 | horse |
Aktuelle Lösung

Ich kenne eine Abfrage, um dies zu erreichen:

SELECT grps.g,
(SELECT v FROM tab
 WHERE g = grps.g
 ORDER BY a DESC, b DESC
 LIMIT 1) AS r
FROM (SELECT DISTINCT g FROM tab) grps
Frage

Aber ich betrachte diese Abfrage eherhässlich. Meistens, weil es a verwendetabhängige Unterabfrage, was sich wie ein echter Leistungskiller anfühlt. Ich frage mich also, ob es eine einfachere Lösung für dieses Problem gibt.

Erwartete Antworten

Die wahrscheinlichste Antwort, die ich auf diese Frage erwarte, wäre eine Art Add-On oder Patch für MySQL (oder MariaDB), das eine Funktion dafür bietet. Aber ich werde auch andere nützliche Inspirationen begrüßen. Alles, was ohne abhängige Unterabfrage funktioniert, ist eine Antwort.

Wenn Ihre Lösung nur für eine einzelne Ordnungsspalte funktioniert, d. H. Nicht unterscheiden kanncat undhorse, zögern Sie nicht, diese Antwort vorzuschlagen, da ich davon ausgehe, dass sie für die meisten Anwendungsfälle immer noch nützlich ist. Zum Beispiel,100*a+b Es wäre wahrscheinlich, die obigen Daten nach beiden Spalten zu ordnen, während immer noch nur ein einziger Ausdruck verwendet wird.

Ich habe ein paar ziemlich hackische Lösungen im Sinn und werde sie vielleicht nach einer Weile hinzufügen, aber ich werde zuerst nachsehen, ob einige nette neue hinzukommen.

Benchmark-Ergebnisse

Da es ziemlich schwierig ist, die verschiedenen Antworten nur durch Betrachten zu vergleichen, habe ich einige Benchmarks für sie durchgeführt. Dies wurde auf meinem eigenen Desktop mit MySQL 5.1 ausgeführt. Die Zahlen lassen sich nicht mit anderen Systemen vergleichen, sondern nur miteinander. Sie sollten wahrscheinlich Ihre eigenen Tests mit Ihren realen Daten durchführen, wenn die Leistung für Ihre Anwendung entscheidend ist. Wenn neue Antworten eingehen, füge ich sie möglicherweise meinem Skript hinzu und führe alle Tests erneut aus.

100.000 Artikel, 1.000 Gruppen zur Auswahl, InnoDb:0,166s fürMvG (aus Frage)0,520s fürRichardTheKiwi2,199s fürxdazz19.24s fürDems (sequentielle Unterabfragen)48,72s füracatt100.000 Artikel, 50.000 Gruppen zur Auswahl, InnoDb:0,356s fürxdazz0,640s fürRichardTheKiwi0,764s fürMvG (aus Frage)51.50s füracattzu lang zumDems (sequentielle Unterabfragen)100.000 Artikel, 100 Gruppen zur Auswahl, InnoDb:0,163s fürMvG (aus Frage)0,523s fürRichardTheKiwi2,072s fürDems (sequentielle Unterabfragen)17,78s fürxdazz49,85s füracatt

So scheint es, dass meine eigene Lösung bisher nicht allzu schlecht ist, selbst mit der abhängigen Unterabfrage. Überraschenderweise schneidet die Lösung von acatt, die ebenfalls eine abhängige Unterabfrage verwendet und die ich daher ungefähr gleich in Betracht gezogen hätte, wesentlich schlechter ab. Wahrscheinlich etwas, das der MySQL-Optimierer nicht bewältigen kann. Die von RichardTheKiwi vorgeschlagene Lösung scheint ebenfalls eine gute Gesamtleistung zu haben. Die beiden anderen Lösungen hängen stark von der Struktur der Daten ab. Bei vielen kleinen Gruppen übertrifft der Ansatz von xdazz alle anderen, während die Lösung von Dems für wenige große Gruppen die beste (wenn auch nicht außergewöhnlich gute) Leistung erbringt.

Antworten auf die Frage(4)

Ihre Antwort auf die Frage