MySQL Mal wieder GROUP BY, COUNT und LEFT JOIN

27o8

abgemeldet
2 Mai 2006
9.028
933
Hab mal wieder ein Problem mit GROUP BY, COUNT und LEFT JOIN :roll:

Folgender Query:
Code:
SELECT mitglieder.werber, COUNT(mitglieder.id) AS menge, COUNT(teilnahmen.id) AS teilnahmen FROM
                                                mitglieder
                                                LEFT JOIN teilnahmen ON teilnahmen.uid=mitglieder.id AND teilnahmen.zeit >= '.$start.' AND teilnahmen.zeit <= '.$ende.'
                                   WHERE mitglieder.status="aktiv" AND mitglieder.werber > 0 AND mitglieder.registrierung >= '.$start.' AND mitglieder.registrierung <= '.$ende.'
                                   GROUP BY teilnahmen.uid, mitglieder.werber
                                   HAVING teilnahmen >= '.$min.'
                                   ORDER BY menge DESC LIMIT 10
Ich möchte zu jedem Werber die Anzahl der Refs die zwischen $start und $ende geworben wurden. Es zählen jedoch nur Refs die zwischen $start und $ende an min. $min Aktionen teilgenommen haben.

liefert mir:

werber = 1
menge = 2

Dabei hat werber 1 nur 1 Ref geworben (der hat allerdings an 2 Aktionen teilgenommen) :-?
 
Oehm, wie waere es eine Subquery zu machen die dir die Werber raussucht die zaehlen (aktionen > 0) und dann mit einer "IN" anfrage darin suchen, damit hast du nicht mehr das Problem.
 
Da hab ich aber ja dann nicht die Menge der User die geworben wurden, und danach möchte ich ja sortieren. Der mit den meisten soll halt zuerst kommen. :think:
 
Mir fällt ohne Beispieldaten auf die Schnelle nur ein, dass Du
Code:
COUNT(DISTINCT mitglieder.id)
schreiben solltest. Denn COUNT zählt die Anzahl der passenden Datensätze, und DISTINCT filtert die Duplikate heraus. Da DISTINCT bei Dir fehlt, bekommst Du immer COUNT(mitglieder.id) = COUNT(teilnahmen.id).
 
Mit DISTINCT geht es, war ja doch einfacher als ich gedacht habe. Muss ich mir unbedingt merken.

Danke :kiss:
 
Will doch noch nicht so wirklich...

Code:
SELECT m2.nickname, mitglieder.werber, COUNT(DISTINCT mitglieder.id) AS menge, COUNT(teilnahmen.id) AS teilnahmen FROM
                                                mitglieder
                                                LEFT JOIN teilnahmen ON teilnahmen.uid=mitglieder.id AND teilnahmen.zeit >= '.$start.' AND teilnahmen.zeit <= '.$ende.' AND teilnahmen.status = 1
                                                LEFT JOIN mitglieder AS m2 ON m2.id = mitglieder.werber
                                   WHERE mitglieder.status="aktiv" AND mitglieder.werber > 0 AND mitglieder.angemeldet >= '.$start.' AND mitglieder.angemeldet <= '.$ende.'
                                    
                                    GROUP BY teilnahmen.uid, mitglieder.werber               
                                   HAVING teilnahmen >= '.$min.'
                                   ORDER BY menge DESC LIMIT 11

Wenn mitglieder.werber nun 2 Refs hat welche die Bedingungen erfüllen taucht er 2x in der Liste mit 1 "menge" statt 1x mit 2 "menge" auf :-?
 
Wenn du nach den Teilnahmen gruppierst, ist das kein Wunder ;)
Denn für den Werbe gibt es für beide Refs natürlich eine Teilnahme ;)
 
Wenn ich nicht danach gruppiere dann kommen ganz komische Ergebnise raus. Der Werber der vorher 2 Einträge hat, hat dann auf einmal 21(!) was nicht sein kann.
 
Schau mal, ob das hier klappt:

PHP:
SELECT werber , COUNT (*)
FROM mitglieder
WHERE ID in
( SELECT UID
FROM teilnahmen 
WHERE zeit BETWEEN '.$start.' AND '.$ende.'
GROUP BY UID
HAVING COUNT(*) >='.$min') 
GROUP BY werber;
 
Super, das scheint soeweit zu funktionieren. Kannst du auch noch paar Zeilen dazu erklären? Hab nämlich so Query in Query noch nie gemacht :p
 
Zuerst wird vom System die innere Query ausgeführt. Das ist die hier:

PHP:
( SELECT UID
FROM teilnahmen 
WHERE zeit BETWEEN '.$start.' AND '.$ende.'
GROUP BY UID
HAVING COUNT(*) >='.$min.')

Als Ergebnis erhalte ich eine Tabelle mit allen Refs ( bzw. deren UIDs ), die zwischen .$start. und .$ende. an mindestens .$min. Aktionen teilgenommen haben. Weil nur die sollen ja Berücksichtigung finden.

Als nächstes hole ich mir alle Werber dieser Refs

PHP:
SELECT werber ...
FROM mitglieder 
WHERE ID in
( gerade ermittelter Liste )

Für jeden Ref, der die Eingangsbedingung erfüllt, taucht jetzt die werber-ID in der Ergebnismenge einmal auf. Nun brauche ich nur noch nach der werber-ID zu gruppieren und die jeweilige Anzahl der Zeilen zu ermitteln

PHP:
SELECT werber , COUNT(*)
...
GROUP BY werber

damit habe ich das geforderte Ergebnis erhalten