PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [MySQL] Left join, Gruppierung, Maximum


Hardwaretoaster
2010-04-08, 15:18:11
Ich stehe hier gerade auf der Leitung. Ich habe eine Tabelle Mitglieder und eine Betätigung. Ich möchte jetzt alle Mitglieder mit ein paar Feldern und wenn vorhanden der neuesten Aktivität.

Meine Überlegung:
select [....] from mitglied m left join betaetigung b on m.Mitgliedsnummer = b.Mitgliedsnummer
group by m.Mitgliedsnummer
having b.datum=max(b.datum)
das ist gültig, liefert aber nichts zurück, irgendwo übersehe ich was, kann mir jemand helfen?

Matrix316
2010-04-08, 15:58:41
probier mal "left outer join" bzw. probier mal ohne having. Kommt dann ein Ergebnis? Vielleicht geht das mit dem Max nicht oder statt MAX(b.Datum) (select max(b.Datum) from betaetigung ).

Hardwaretoaster
2010-04-08, 16:34:17
Ohne having geht es, dann halt ein beliebiger Datensatz der Gruppierung, nicht der mit dem höchsten Datum, outer und subselect machen keinen Unterschied.

interzone
2010-04-08, 17:03:44
so auf die Schnelle...
Du benötigst eine Unterabfrage, in der zu jedem Mitglied das Max(Datum) über eine Gruppierung ermittelt wird.
Anschließend machst Du einen Join über die Mitgeliedsnummer zu dieser Unterabfrage und joinst nochmal auf die Betätigung, um die passende Aktivität zu finden.

Könnte so aussehen (weiß nicht, ob mysql-konform):
select distinct b2.Aktivitaet,
a.Mitgliedsnummer,
b.Datum
from mitglied m left join
(select b.Mitgliedsnummer,
MAX(b.Datum) as Datum
from betaetigung as b
Group by b.Mitgliedsnummer) As b On m.Mitgliedsnummer = b.Mitgliedsnummer
Left Join betaetigung as b2 On b2.Mitgliedsnummer = m.Mitgliedsnummer
And b2.Datum = b.Datum

Hardwaretoaster
2010-04-08, 23:22:13
Konzept habe ich wohl verstanden, an der MySQL-Konformität (ich vermute der des subselects im join) knabber ich noch:

#1054 - Unknown column 'b.Datum' in 'field list'

gereggter Gast
2010-04-09, 08:22:31
so auf die Schnelle...
Du benötigst eine Unterabfrage, in der zu jedem Mitglied das Max(Datum) über eine Gruppierung ermittelt wird.
Anschließend machst Du einen Join über die Mitgeliedsnummer zu dieser Unterabfrage und joinst nochmal auf die Betätigung, um die passende Aktivität zu finden.

Könnte so aussehen (weiß nicht, ob mysql-konform):
select distinct b2.Aktivitaet,
a.Mitgliedsnummer,
b.Datum
from mitglied m left join
(select b.Mitgliedsnummer,
MAX(b.Datum) as Datum
from betaetigung as b
Group by b.Mitgliedsnummer) As b On m.Mitgliedsnummer = b.Mitgliedsnummer
Left Join betaetigung as b2 On b2.Mitgliedsnummer = m.Mitgliedsnummer
And b2.Datum = b.Datum
Der letzte left join ist unnötig, wenn in dem Subselect einfach nach Datum und Betätigung gefragt wird.

Hier etwas mysql konformer:

SELECT mitglied.Mitgliedsnummer, tmp.Datum, tmp.Aktivitaet
FROM mitglied
LEFT JOIN (
SELECT Mitgliedsnummer, MAX(Datum) as Datum
FROM betaetigung
GROUP BY Mitgliedsnummer
) AS tmp ON mitglied.Mitgliedsnummer = tmp.Mitgliedsnummer

interzone
2010-04-09, 08:48:25
Der letzte left join ist unnötig, wenn in dem Subselect einfach nach Datum und Betätigung gefragt wird.

Hier etwas mysql konformer:

SELECT mitglied.Mitgliedsnummer, tmp.Datum, tmp.Aktivitaet
FROM mitglied
LEFT JOIN (
SELECT Mitgliedsnummer, MAX(Datum) as Datum
FROM betaetigung
GROUP BY Mitgliedsnummer
) AS tmp ON mitglied.Mitgliedsnummer = tmp.Mitgliedsnummer

Aber in Deinem Subselect wird die Aktivität nicht selektiert. Die kannst Du dann doch nicht einfach referenzieren.

gereggter Gast
2010-04-09, 08:59:15
Aber in Deinem Subselect wird die Aktivität nicht selektiert. Die kannst Du dann doch nicht einfach referenzieren.
Scheiße, hast natürlich Recht. Habe das Feld beim Abschreiben vergessen.

Hier noch mal das Subselect:

SELECT Mitgliedsnummer, Aktivitaet, MAX(Datum) as Datum
FROM betaetigung
GROUP BY Mitgliedsnummer, Aktivitaet

Falls es pro Mitglied zwei Aktivitäten zur selben Zeit gegeben haben sollte, habe ich auch gleich mal danach gruppiert.

Hardwaretoaster
2010-04-09, 12:18:50
Funktioniert fast. Mit Gruppierung gibt er auch Aktivitäten älteren Datums aus, da diese ja unterschiedlich. Ohne Gruppierung kommt nur das max-Datum raus, allerdings kann es dann passieren, dass die Aktivität die falsche ist, weil eben nicht gruppiert.

interzone
2010-04-09, 16:00:46
Funktioniert fast. Mit Gruppierung gibt er auch Aktivitäten älteren Datums aus, da diese ja unterschiedlich. Ohne Gruppierung kommt nur das max-Datum raus, allerdings kann es dann passieren, dass die Aktivität die falsche ist, weil eben nicht gruppiert.
Schon meine Lösung ausprobiert?
Wenn Du aus dem a.Mitgliedsnummer ein m.Mitgliedsnummer machst, dann sollte es passen.

Hardwaretoaster
2010-04-10, 13:05:12
Schon meine Lösung ausprobiert?
Wenn Du aus dem a.Mitgliedsnummer ein m.Mitgliedsnummer machst, dann sollte es passen.

Schande über mich!!

Ja, hatte es ja gleich zu Anfang probiert und es ging zunächst nicht.
War ein ganz dummer Fehler: Im subselect wird die Spalte mit dem Max benannt und dann außen abgefragt, da war ich nicht identisch (ch sollte mir doch hin und wieder die Zeit nehmen konzentriert NUR an einer Sache und nicht an 3 Sachen gleichzeitig zu wurschteln...)

Es scheint zu gehen, werde noch etwas testen, falls ich noch an etwas hängenbleibe schreib ich ggf. nochmal.

Hardwaretoaster
2010-04-12, 08:37:47
Jetzt mal wieder Zeit gehabt weiterzumachen:

Jetzt wird's lustig: #1349 - MySQL kann keine SELECT in der FROM-clause wenn's ein view werden soll. Workaround wäre zwi Views draus zu machen. Muss das echt sein?

interzone
2010-04-12, 23:26:40
Jetzt mal wieder Zeit gehabt weiterzumachen:

Jetzt wird's lustig: #1349 - MySQL kann keine SELECT in der FROM-clause wenn's ein view werden soll. Workaround wäre zwi Views draus zu machen. Muss das echt sein?
ich habe mich über mySQL schon einige Male aufgeregt - sind schon einige Limitierungen drin. Zum Glück habe ich nicht so viel damit zu tun.
Wie man eine View macht, weißt Du aber?

Du benötigst aber (falls dem so ist) nur eine View - und zwar die, die Dir das MAX(Datum) des Mitglieds liefert (Gruppiert auf Mitglied - das wäre die Unterabfrage aus dem Beispiel). Dann musst Du dazu, wie in meinen Fall, die Aktivität dazu finden (Join auf Mitglied UND Datum) - also den Join auf die Unterabfrage(jetzt View) basteln.

Versuchs mal - wenn's nicht klappt, melde Dich nochmal.

Hardwaretoaster
2010-04-13, 06:03:31
Ja, View bauen ist kein Problem. Geht auch so, wie ich mir das vorstelle. Aber ärgerlich bleibt es...