Gruppen anhand eines Wertes einer nicht gruppierten Spalte auswählen
am 26.01.2007 23:07:29 von Andreas FischerHallo zusammen!
(Nur am Rande:
Wegen Instantrails verwende ich gezwungenermassen noch mysql 4.1.9)
Für folgende vereinfachte Tabelle t_1
t_1:
============
id A B C
------------
1 1 1 1
2 1 1 1
3 2 1 1
4 2 2 2
5 2 5 5
6 3 1 1
7 3 5 5
============
möchte ich bei einer Gruppierung nach Spalte A und B die Größe
(Anzahl an Zeilen) jeder einzelnen Gruppe herausfinden, die einen
bestimmten Wert in der Spalte C enthält.
Wenn der gesuchte Wert der Spalte C zufällig der Maximalwert dieser
Spalte ist, liefert folgender Query sehr schnell das Ergebnis:
SELECT A,B,COUNT(C)
FROM t_1
GROUP BY A,B
HAVING MAX(C)=5
Das Problem:
Konkret bräuchte ich eine Version in der man Gruppen anhand eines
beliebigen Wertes von C auswählen kann und die unter realen Bedingungen
genauso oder vergleichbar schnell ist wie die obige Variante.
Ich dachte und denke eigentlich nach wie vor, dass das einfach möglich sein
müsste, habe aber bisher weder im Internet noch selbst eine praktikable
Lösung gefunden. (gescheiterte Versuche siehe unten)
Ausserdem würde mich sehr interessieren ob es prinzipiell irgendeine
Möglichkeit mittels SQL gibt direkt auf die Werte der "nicht-Group-By"-
Spalten innerhalb einer Gruppierung zuzugreifen, also die Werte auf die
z.B. Aggregate-Functions Zugriff haben müssen.
Oder muss ich dafür zwangsweise auf user defined functions zurückgreifen?
Dem Manual nach zu urteilen vermute ich mal das letzteres der Fall
sein wird, habe aber weder dort noch sonstwo im Netz eine für mich 100%
eindeutige Antwort dazu gefunden.
http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-field s.html
Falls das für jemanden von Interesse ist beschreibe ich noch kurz was
bei mir bisher nicht geklappt hat:
In einer Vorstufe zu meinem entsprechenden realen Problem habe ich
ca. 20000 Datensätze die bei einer Gruppierung nach "A" und "B" in
ca. 1000 Gruppen aufgeteilt werden.
Dafür habe ich drei funktionsfähige Varianten.
(Die Laufzeiten sind bei 20000 Datensätzen a 1000 Gruppen)
1. eine analoge zur obigen Version die 3 Sekunden braucht
2. eine Variante mit einem inner join die knapp eine Minute braucht:
(für den speziellen C-Wert, die Spalten A,B,C selektieren und mit
Zeilen
gleicher A und B-spalte aus t_1 joinen)
3. Eine Abänderung der 1.Variante mit Group by .. Having (A,B) In SELECT
.....
-- die 4 Minuten braucht
zu 1.:
wegen MAX() zu speziell => Unbrauchbar
zu 2. und 3.:
Ich vermute mal das das Verhältnis der Laufzeiten von
(1.) zu (2. und 3.) irgendwo bei
linear(1.) zu quadratisch und oder schlimmer(2.,3.) liegt
Laufzeit für 2. und 3.ist jedenfalls zu hoch und wird bei realeren,
grösseren Datenmengen wohl völlig inakzeptabel werden.
Gruß,
Andreas