SELECT/JOIN/SQL-statement richtig formulieren
Paco
- datenbank
Hallo!
Ich habe Schwierigkeiten eine SQL-Abfrage zu formulieren, die die Ausgabe erziehlt, die ich brauche. Ich bastele an einem Projektmanagement-Tool (Apache und mySQL-Datenbank) das Projekte, Benutzer und Aufgaben beinhaltet. mein Datenbankdesign sieht (dank EKKis Hilfe) mittlerweile folgendermaßen aus:
tabelle projekte
ID | projekt| ...
---+--------+-----
1 | blabla |
2 | blubb |
users
UserID | UserName | ...
-------+----------+-----
1 | Hans |
2 | Jochen |
3 | Peter |
rolle
ID | name | ...
---+---------------+-----
1 | Projektleiter |
2 | Technik |
3 | Grafik |
dispo
ID | projekt_id | user_id | rolle_id | ...
---+------------+-------------+----------+-----
1 | 1 | 1 | 1 |
2 | 1 | 3 | 2 |
3 | 1 | 4 | 3 |
4 | 2 | 2 | 1 |
5 | 2 | 1 | 2 |
6 | 2 | 3 | 3 |
Meine Abfrage bisher:
SELECT projekt, rolle, GROUP_CONCAT(DISTINCT UserName)
FROM projekte
LEFT JOIN dispo
ON projekte.id = dispo.projekt_id
LEFT JOIN users
ON dispo.user_id = users.UserID
JOIN rollen
ON dispo.rolle_id = rollen.id
GROUP BY projekt
funktioniert und liefert mir z.B.:
projekt | rolle | GROUP_CONCAT(DISTINCT UserName)
--------+----------------+--------------------------------
blabla | projektleiter | Hans
blubb | Technik | Hans, Jochen
blerch | grafik | Jochen, Peter
Was ich haben möchte, ist eine Ausgabe wie folgende:
projekt | projektleiter | technik | grafik
--------+----------------+---------+--------
blabla | Hans | Hans |
| | |Hans
| | |Jochen
blerch | Jochen | Jochen |Peter
| | Hans |
Also die Werte der Rollen als Spaltenüberschriften. Das bekomme ich aber nicht hin. Wie muß ich denn JOINen um "SELECT projekt, projektleiter, technik..." ausführen zu können?
Vielen Dank,
Paco
moin,
SELECT projekt, rolle, GROUP_CONCAT(DISTINCT UserName)
FROM projekte
LEFT JOIN dispo
ON projekte.id = dispo.projekt_id
LEFT JOIN users
ON dispo.user_id = users.UserID
JOIN rollen
ON dispo.rolle_id = rollen.id
GROUP BY projektfunktioniert und liefert mir z.B.:
jeder hat ja seinen stil, wie man abschreiben erstellt, aber bei diese darstellung ist schon nicht einfach zu lesen. nur als tipp gemeint, versuche mal eine andere darstellung, auch aliasnamen helfen immens.
nun aber zu der eigentlichen frage, diese abfrage kann so nicht funktionieren, du unterliegst einem mysql bug. dafür gibt es mittlerweile soviel postings hier im forum über diesen "bug", dass wir mysql eine rechnung stellen sollten. du gibst die spalten "rolle" aus, ohne darüber gruppiert zu haben.
das andere ist, du machst auf die tabelle "dispo", die du vorher mit einem OUTER LEFT JOIN eingebunden hast, zusätzlich danach noch einen INNER JOIN auf eine die tabelle "rollen". das macht keinen sinn, weill du dann wieder datensätze verlieren kannst, die du durch den LEFT JOIN eigentlich haben wolltest.
und um dein problem zu lösen, dass du Datensätze als spalten darstellen willst, das geht, wenn du die Anzahl der Spalten genau weisst, sprich eine spalte für technik, eine für grafik .... also bekannt und endlich sind. dazu kannst du korrelierte unterabfragen benutzen. unterabfragen bei mysql gehen aber erst ab version 4.1. und da du uns version verschwiegen hast....
Ilja
jeder hat ja seinen stil, wie man abschreiben erstellt, aber bei diese darstellung ist schon nicht einfach zu lesen. nur als tipp gemeint, versuche mal eine andere darstellung, auch aliasnamen helfen immens.
Ups, da is die Formatierung beim copy-pasten flöten gegangen, sorry.
nun aber zu der eigentlichen frage, diese abfrage kann so nicht funktionieren, du unterliegst einem mysql bug. dafür gibt es mittlerweile soviel postings hier im forum über diesen "bug", dass wir mysql eine rechnung stellen sollten. du gibst die spalten "rolle" aus, ohne darüber gruppiert zu haben.
Was ist denn nun genau der Bug? Die Abfrage funktioniert doch. Und was meinst du mit ausgeben ohne vorher zu gruppieren?
das andere ist, du machst auf die tabelle "dispo", die du vorher mit einem OUTER LEFT JOIN eingebunden hast, zusätzlich danach noch einen INNER JOIN auf eine die tabelle "rollen". das macht keinen sinn, weill du dann wieder datensätze verlieren kannst, die du durch den LEFT JOIN eigentlich haben wolltest.
Ich dachte mir das so: tabelle projekte>=tabelle dispo>=users=rolle. Also benutzer/rolle als "kleinster gemeinsamer Nenner", bzw als Teilmenge von dispo, dispo als teilmenge von projekte. Welche datensätze verliere ich denn da?
und um dein problem zu lösen, dass du Datensätze als spalten darstellen willst, das geht, wenn du die Anzahl der Spalten genau weisst, sprich eine spalte für technik, eine für grafik .... also bekannt und endlich sind. dazu kannst du korrelierte unterabfragen benutzen. unterabfragen bei mysql gehen aber erst ab version 4.1. und da du uns version verschwiegen hast....
Meine Serverversion ist 5.0. Also dann werde ich mich mal mit den korrelierten unterabfragen auseinandersetzen...
Vielen Dank schonmal
yo,
Was ist denn nun genau der Bug? Die Abfrage funktioniert doch. Und was meinst du mit ausgeben ohne vorher zu gruppieren?
eben, alle anderen dbms ausser mysql würde dir bei dieser abfrage eine fehlermeldung ausgeben und zwar zurecht. die regel besagt, du darfst nur spalten innerhalb einer gruppierung ausgeben, über die auch gruppiert wurde oder aber bestandteil einer aggregat-funktion sind. wenn dir die problematik nicht bewußt ist, suche hier einfach im forum danach.
Ich dachte mir das so: tabelle projekte>=tabelle dispo>=users=rolle. Also benutzer/rolle als "kleinster gemeinsamer Nenner", bzw als Teilmenge von dispo, dispo als teilmenge von projekte. Welche datensätze verliere ich denn da?
hast du den erfahrungen mit LEFT JOINS, bzw. weißt du wofür sie verwendet werden ? wenn dem so ist, sollte dir auch klar ein, dass ein OUTER JOIN (LEFT JOIN) NULL werte zurück gibt, wenn es keine passenden Datensatz auf der anderen tabellenseite findet, in deinem falle wäre es die tabelle dispo. somit hätte auch die spalte dispo.rolle_id einen NULL wert und dann werden die datensätze über den INNER JOIN mit der "rolle" tabelle wieder wegfallen. mit anderen worten, dein OUTER JOIN an der stelle ist sinnlos.
Ilja