Hallo und guten Tag Rolf,
SELECT DISTINCT projekt, modul, funktion FROM rechte WHERE r.id_user = $user OR r.id_group IN (SELECT id FROM groups g WHERE g.id_user = $user)
So hatte ich es wohl im Bauch, kam aber nicht mehr auf die richtige Syntax. Bin eben eingerostet.
Es gibt allerdings DB-Systeme, bei denen eine OR-Bedingung extrem inperformant ist und zu einem Table-Scan führt. Auf unserem IBM Großrechner war OR darum lange verboten. Ob InnoDB in MySQL dazu gehört, weiß ich nicht. Wenn Du nicht viele User hast, ist das wurscht. Wenn Du ein Performance-Problem befürchtest, kannst Du es auch so machen:
SELECT r1.projekt, r1.modul, r1.funktion FROM rechte r1 WHERE r1.id_user = $user UNION SELECT r2.projekt, r2.modul, r2.funktion FROM rechte r2 WHERE r2.id_group IN (SELECT g.id FROM groups g WHERE g.id_user = $user)
Aber das gefällt mir besser, wenn man damit gleichzeitig die Gefahr beseitigt, das DBMS zum Stehen zu bringen.
Es könnten mittelfristig ca. 300.000 User werden, die aber selbstverständlich nicht alle gleichzeitig und jeden Tag zugreifen.
SELECT DISTINCT im ersten Beispiel bzw. der UNION im zweiten Beispiel eliminieren Duplikate, d.h. wenn Du ein Recht auf mehreren Wegen erhältst, bekommst Du trotzdem nur eine Ergebniszeile dafür. Damit diese Vorverdichtung greift, musst Du die selektierten Spalten auf die reinen Rechte begrenzen und die IDs heraushalten. Wenn Du die Duplikate unbedingt haben willst, musst Du den DISTINCT weglassen bzw. dem UNION ein ALL hinzufügen.
Duplikate dürften eigentlich nicht vorkommen, da entweder das Feld id_user, oder das Feld id_group eines Datensatzes belegt sein darf. Darum weiß ich auch nicht, ob das Design nicht noch eine Macke hat.
Alternativ könnte man Numernkreise vergeben oder bei einer gemeinsamen FK-ID in der Tebelle rights mit Präfix arbeiten... Aber das würde das Ganze bei der Abfrage vermutlich auch wieder langsam machen.
Grüße
TS