Supportnet / Forum / Skripte(PHP,ASP,Perl...)
nicht vorhanden und vorhanden ids zählen
Frage
hallo!
ich hab mal wieder ein problemchen und so spät komm ich einfach nicht auf die lösung.
ich habe 2 tabellen:
eine (gruppenzugehörigkeit: gz) mit je der id einer person und der id einer gruppe in der sich diese person befindet. jede person gibts nur in einer gruppe.
in der anderen (gruppennamen: gn) sind auch 2 spalten, eine mit den ids der gruppen, die 2. beinhalt die namen der gruppen.
so, jetzt würde ich gerne wissen, wie viel personen in jeder gruppe sind und nach anzahl dieser absteigend sortieren. problem ist, dass eine gruppe in meinem ergebnis noch nicht vorkommt, wenn sie leer ist.
mein bisheriges statement lautet so:
SELECT
gn.id,
gn.name,
COUNT( * ) AS amount FROM
gn , gz
WHERE
gn.id = gz.groupid
GROUP BY gn.id
ORDER BY amount DESC
wie muss ich das erweitern, dass die ids, die nicht vorkommen, mit amount = 0 am ende stehen?
Antwort 1 von semi
gn LEFT OUTER JOIN gz
Antwort 2 von semi
Das ganze dann so
SELECT gn.id, gn.name, CASE WHEN gz.groupid IS NOT NULL THEN count(*) ELSE 0 END AS amount
FROM gn LEFT OUTER JOIN gz
ON gn.id = gz.groupid
GROUP BY gn.id, gn.name
ORDER BY amount DESCAntwort 3 von semi
Ehmm noch 'ne Alternative mit IF statt CASE
IF(gz.groupid IS NOT NULL,count(*),0)
Gute Nacht.
IF(gz.groupid IS NOT NULL,count(*),0)
Gute Nacht.
Antwort 4 von f*euervogel
wow, dankeschön!!!
gut nacht!
gut nacht!
Antwort 5 von f*euervogel
oh mann, dieser ganze JOIN-Schnulli ist komplizierter als ich dachte...:-/
Antwort 6 von mr_x_hacker
Zu dem "Join-Schnulli" kannst Dir mal das Kapitel 3 angucken :-)
Link
Das ist zwar in relationaler Algebra, aber wenn man es da nicht einmal gesehen hat, wird in SQL schwierig...
Außerdem kann man sich imho in SQL immer um das Schlüsselwort "Join" drücken, jedenfalls hab ich es bisher immer irgendwie anders gemacht :-)
Ach ja, man beachte die "semi"-joins ^^
Ciao Sascha
Link
Das ist zwar in relationaler Algebra, aber wenn man es da nicht einmal gesehen hat, wird in SQL schwierig...
Außerdem kann man sich imho in SQL immer um das Schlüsselwort "Join" drücken, jedenfalls hab ich es bisher immer irgendwie anders gemacht :-)
Ach ja, man beachte die "semi"-joins ^^
Ciao Sascha
Antwort 7 von f*euervogel
@sascha: wenns es geht, dann zeig mir doch bitte eine lösung meines problems ohne JOIN ...? ich komm nämlich nicht drauf...
Antwort 8 von f*euervogel
vielen vielen lieben dank semi, ich hab mich durch JOIN und CASE lerning by first reading then doing gekämpft und bin nun um einiges weiter!!! dankedankedanke
*beispielhaftesfeedbackgibt* :)
*beispielhaftesfeedbackgibt* :)
Antwort 9 von f*euervogel
wobei der unterschied zwischen LEFT OUTER und INNER ist mir noch nicht so ganz klar...statt LEFT OUTER kann ich ja auch einfach LEFT schreiben...aber INNER
*nachschlägt*
*nachschlägt*
Antwort 10 von f*euervogel
aha!
Der Unterschied zwischen INNER und OUTER JOINS ist der, daß OUTER JOINS auch dann Daten der führenden Tabelle selektiert, wenn keine passende Verknüpfung existiert.
Der Unterschied zwischen INNER und OUTER JOINS ist der, daß OUTER JOINS auch dann Daten der führenden Tabelle selektiert, wenn keine passende Verknüpfung existiert.
Antwort 11 von mr_x_hacker
Also zuerst, Du hast es so gewollt *g*
Das folgende ist weder schön, noch effizent, noch sollte es jemals benutzt werden, aber es ist ein join ohne join-Befehl ;-)
Wegen der Subselects geht es natürlich auch net in mysql ;-)
Aber es funzt, und enthält keine fiesen Wörter wie case, else, if, join, usw!
Ciao Sascha
Das folgende ist weder schön, noch effizent, noch sollte es jemals benutzt werden, aber es ist ein join ohne join-Befehl ;-)
select * from
((select gn.name, count(*) as amount from gz, gn where gz.g_id = gn.id group by gn.name)
union
(select gn.name, 0 as amount from gn where gn.id not in (select distinct g_id from gz))) temp
order by temp.amount descWegen der Subselects geht es natürlich auch net in mysql ;-)
Aber es funzt, und enthält keine fiesen Wörter wie case, else, if, join, usw!
Ciao Sascha
Antwort 12 von mr_x_hacker
Jo, der outer join übernimmt auf jeden Fall alle Zeilen der ersten Relation und füllt ggf. die Attribute aus der 2ten Rel. mit 'null' auf, falls in der 2ten kein join-Partner gefunden wird.
Der normale inner join übernimmt nur die Zeilen, die einen join-Partner finden.
Das war ja semis Spielchen, die 'null' dann durch 0 zu ersetzen, dann hast Deine Anzahlen...:-)
Ciao Sascha
Der normale inner join übernimmt nur die Zeilen, die einen join-Partner finden.
Das war ja semis Spielchen, die 'null' dann durch 0 zu ersetzen, dann hast Deine Anzahlen...:-)
Ciao Sascha
Antwort 13 von semi
Man nimmt halt was unterstützt wird und am besten
ohne temporäre Zwischentabellen, wie
bei Subselect.
Auch mit Union kein Problem.
Gruß,
Michael
ohne temporäre Zwischentabellen, wie
bei Subselect.
Auch mit Union kein Problem.
SELECT gn.id, gn.name, count(*) as amount
FROM gn, gz
WHERE gn.id = gz.groupid
GROUP BY 1, 2
UNION
SELECT gn.id, gn.name, 0 as amount
FROM gn
WHERE gn.id NOT IN (SELECT DISTINCT gz.groupid FROM gz)
ORDER BY 3 DESCGruß,
Michael
Antwort 14 von semi
Ups, in Antwort 11 war schon was mit UNION, sorry :-)
Antwort 15 von f*euervogel
wisst ihr was? ich bin froh so wies grad bei mir funktioniert, hab das mit joins grad gut genug gerafft...der trickt mit dem CASE....0....: sonst zählt er bei mir als anzahl 1 statt 0 bei den zeilen, die kein gegenstück haben.

