Bestimmte Zeilen nach einem Select zusammenführen
MichiLee
- datenbank
Hallo Forum,
mein Firefox geht nach einem Update seit 2-3 Tagen nicht mehr, so dass ich auf meine alten Nachrichten nicht antworten konnte. (Hole ich bei Gelegenheit nach, falls ich mich noch bei jemand Bedanken muss oder falls doch noch Fragen ausstehen)
Wie dem auch sei.
Ich mache ein Select auf eine Datenbank und erhalte in etwa solch ein Ergebnis:
BriefingID Name RoleID Right UserID
2 Bla 4 2 2
2 Bla 2 1 2
2 Bla 3 1 2
2 Bla 4 2 3
3 Bla 2 1 4
Es kann also vorkommen, dass ein Benutzer bei einem Briefing mehrere Rolen haben kann und dementsprechend auch verschiedene Rechte.
Ich will nur allen Briefings alle Benutzer anlegen (mehrmals gelistete User sollen natürlich einmal angelegt werden)
Deshalb überlege ich mir, wenn ein User im Ergebnis mehrmals in einem Briefing auftaucht, dass ich die Zeilen nach UserID zusammenführe und als Right die höchste genommen wird nach dem zusammenführen (Damit er die höchsten Rechte besitzt)
Zudem will ich aber auch in eine Vector<Roles> des Userobjekts, alle Rollen eines Users aufnehmen.
Wie stelle ich das am besten an?
Ich leg ein UserObjekt an und mache ein Select, was für Rollen er in einem Briefing hat und speichere alle Rollen in den Vector. Danach führe ich nochmals ein Select, führe bei mehreren Usern alle Zeilen nach Usern zusammen und nehme die höchste ID.
Meine Frage nun: Wie führe ich die Zeilen zusammen?
(Besser wäre es eventuell alles in einem Schritt, aber die erste While-Schleife muss alles durchgehen und nur für einen User, praktisch alle Rollen speichern. (Kein anlegen eines gleichen Users doppelt) und danach die höchsten Rechte setzen)
viele Grüße
Michi
Hallo,
BriefingID Name RoleID Right UserID
2 Bla 4 2 2
2 Bla 2 1 2
2 Bla 3 1 2
2 Bla 4 2 3
3 Bla 2 1 4Meine Frage nun: Wie führe ich die Zeilen zusammen?
Ich denke, GROUP BY ist das was Du suchst
SELECT BriefingID, Name, RoleID, MAX(Right), UserID GROUP BY UserID
oder so ähnlich sollte klappen.
Aber warum eigentlich zwei Selects? Wenn Du erstmal ein User-Objekt hast mit einem Vektor aller Rechte, sollte es kein großes Problem sein, eine Methode für dieses User-Objekt zu basteln ("getHighestRight()" oder so) welches von diesem User das höchste Recht ausgibt. Dann solltest Du noch eine Methode haben, um neue Rechte dem Rechtevektor hinzuzufügen (nennen wir sie mal "addRightToVector(right)").
Dann brauchst Du nur noch einen Hash (respektive ein Array in PHP, eine HashMap in Java or whatever), welcher zu jeder User-ID das User-Objekt speichert.
Bei jedem Datensatz aus dem Select verfährst Du dann wie folgt (Pseudo-Code in einer Phantasie-Programmiersprache):
1.) Datensatz d=(BriefingID,Name,RoleID,Right,UserID)
2.) Ist für UserID "d.UserID" schon ein Objekt im Hash/dem Array/der HashMap?)
3.) JA: objekt_aus_hash.addRightToVector(d.Right);
4.) NEIN:
neuerUser = new User(d);
hash.put(d.UserID, neuerUser);
Wenn die Schleife durchgelaufen ist, hast Du einen Hash/eine HashMap/ein Array, welches jeden User (jede UserID) genau einmal enthält, und jeder User aus dieser Map kennt sowohl sein höchstes Recht (getHighestRight()) als auch seine verschiedenen Einzelrechte.
Mehrere SQL-Aufrufe sind i.d.Regel teuer (Zeit- und Lastintensiv)!
Hope that helps,
Viele Grüße,
Jörg
Hi Jörg,
super dankeschön, zeitgleich hab ich gepostet, dass ich über das Stichwort "GROUP BY" gefunden habe. (Wobei mich hier das Sortieren/Zusammenführen interessiert) Die Idee mit der Hashmap unten ist auch wirklich sehr gut, so könnte ich es eigentlich mit einem SELECT dann machen. Irgendwie Perfekt.
Könnte ich aber fragen, was dein MAX(rightID) in der Query macht? Ist es genau das Problem mit dem ORDER BY, wenn ich das mit zwei Selects gemacht hätte?
Grüße
Hallo,
Könnte ich aber fragen, was dein MAX(rightID) in der Query macht? Ist es genau das Problem mit dem ORDER BY, wenn ich das mit zwei Selects gemacht hätte?
ChrisB hat das glaube ich in seinem Post auch schon angerissen, hier aber nochmal eine Ergänzung:
ORDER BY bestimmt nur die Reihenfolge der Ausgabe.
Du kannst mit "ORDER BY" immer nur sagen, in welcher Reihenfolge Du Datensätze haben willst, an den Datensätzen selbst ändert sich aber nichts.
Order By steht üblicherweise immer ganz am Schluss eines Selects.
Anders bei "GROUP BY": Es gibt verschiedene sog. Agregatsfunktionen in SQL mit denen Du eine bestimmte Menge von Datensätzen agregieren (= zusammenfassen kannst) - z.b. aufsummieren, durchzählen oder wie in Deinem Fall das Maximum bilden.
Mit GROUP BY definierst Du, nach welchem Kriterium die einzelnen Mengen, die zusammengefasst werden sollen, gebildet werden.
Lässt Du es weg, wird eine einzige große Menge mit allen Datensätzen gebildet, Du erhältst dann also genau ein Ergebnis zurück.
Beispiel:
SELECT MAX(Right) FROM user
lies: "Liefere mir das Maximum der Spalte "Right" aus der Tabelle "user".
Dies liefert (keine große Überaschung ;)) einen einzigen Datensatz, nämlich den höchsten Wert von "Right" in der Tabelle user.
Jetzt mit Group By:
SELECT MAX(Right) FROM USER GROUP BY userid
lies: "Bilde für jede userid eine eigene Gruppe von Datensätzen. Jetzt gib mir für jede dieser Gruppen das Maximum der Spalte "Right".
Liefert Dir für jede UserID genau einen Datensatz, nämlich das Maximum der Spalte Right.
Hoffe das machts etwas klarer.
Viele Grüße,
Jörg
hi,
ich habe zumindest das Stichwort.
GROUP BY sollte bestimmt funktionieren. Nur sollte ich ja davor ein ORDER BY rightID machen, da meckert er dann. Ohne ORDER BY gehts.
Hi,
GROUP BY sollte bestimmt funktionieren. Nur sollte ich ja davor ein ORDER BY rightID machen, da meckert er dann.
„Er meckert“ ist keine brauchbare Aussage.
Abgesehen davon, dass es irgendwie per se blödsinnig ist, immer und überall von „er“ zu reden - wenn wir nicht wissen, *was* „er“ meckert, dann können wir dir auch nicht sagen, was „ihn“ stört.
Ohne ORDER BY gehts.
Höchstens vermuten kann man hier, dass du schlicht und einfach die definierte Reihenfolge, in der die Klausel stehen müssen, ignoriert hast.
MfG ChrisB
Hi,
Abgesehen davon, dass es irgendwie per se blödsinnig ist, immer und überall von „er“ zu reden - wenn wir nicht wissen, *was* „er“ meckert, dann können wir dir auch nicht sagen, was „ihn“ stört.
Ohne ORDER BY gehts.
hab als erstes ein ORDER BY gemacht und danach ein GROUP BY:
SELECT * FROM projects AS P INNER JOIN castings AS C ON P.projectID=C.projectID INNER JOIN
employees AS E on C.employeeID=E.employeeID INNER JOIN roles AS R ON C.roleID=R.roleID WHERE
P.projectID='89' ORDER BY R.rightID asc GROUP BY E.employeeID
Die Fehlermeldung dazu:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GROUP BY E . employeeID
LIMIT 0, 30' at line 1
Dürfte ich nur noch kurz fragen, was in einer Java Hashtable eigentlich passiert, wenn ich zu einem bereits vorhandenen Key erneut irgend ein Value schreibe? Fehlermeldung oder wird es einfach überschrieben? (Zur Not teste ich das schnell durch)
Grüße
Hi,
hab als erstes ein ORDER BY gemacht und danach ein GROUP BY:
Dann geh' bitte im Handbuch nachlesen, wie die korrekte Reihenfolge der Klauseln lautet.
MfG ChrisB
hi,
hab als erstes ein ORDER BY gemacht und danach ein GROUP BY:
Dann geh' bitte im Handbuch nachlesen, wie die korrekte Reihenfolge der Klauseln lautet.
wenn ich das richtig verstanden habe, muss das ORDER BY nach GROUP BY auftauchen. Dann sortiert er das ganze jedoch, nachdem er gruppiert hat. Will man eine maximale Spalte bei einer Gruppierung zusammenführen, muss man wohl MAX(Spaltenname) schreiben. (Hoffentlich habe ich das richtig verstanden und kann in Ruhe dann schlafen)
Wünsche allen ne gute nacht
Grüße
Hi,
wenn ich das richtig verstanden habe, muss das ORDER BY nach GROUP BY auftauchen.
Das hast du richtig verstanden,
Dann sortiert er
meine Hinweise bzgl. „ihm“ aber offenbar nicht.
das ganze jedoch, nachdem er gruppiert hat.
Das ist immer so.
Will man eine maximale Spalte bei einer Gruppierung zusammenführen, muss man wohl MAX(Spaltenname) schreiben.
Man gruppiert, *um* das Maximum ermitteln zu können - über eben dieser Gruppierung.
Dein SELECT * ist in Kombination mit der gewählten Gruppierung übrigens ungültiges SQL - du darfst nur die Inhalte von Spalten selektieren, die Teil deiner Grupierung sind.
MySQL lässt dir das zwar durchgehen - aber die Ergebnisse unterliegen für alle Spalten, die nicht Teil der Gruppierung sind, mehr oder weniger dem Zufall.
MfG ChrisB