Etwas "kompliziertere?" Abfrage

Etwas "kompliziertere?" Abfrage

am 20.09.2006 16:43:11 von Peter Stoss

Hallo,
ich habe drei Tabellen (MySQL 4.0 steht zur Verfügung).

Tabelle 1: Benutzer

id,name
1,irgendwer
2,einanderer
3,nocheinanderer


Tabelle 2 verwaltet die Codes und wer dafür zuständig sein darf
(einige tausend)

id,code,benutzer
1,ABC,1
2,DEF,2
3,DEF,3
4,GHI,3
5,JKL,3


Tabelle 3: Codezuordnungen

id,code_a,code_b
1,ABC,DEF
2,DEF,ABC
3,DEF,GHI
4,GHI,ABC


Ziel ist es nun aus Tabelle 3 DIE Codes rauszusuchen, die z.B. von
Benutzer 1 verwaltet werden können. Wichtig dabei: es reicht, wenn
einer der beiden Codes (code_a oder code_b) von dem Benutzer verwaltet
werden darf.
Im Beispiel also bekommen angezeigt aus Tabelle 3:

Benutzer 1 (ihm ist lt. Tabelle nur Code ABC zugeordnet):
1,ABC,DEF
4,GHI,ABC

Benutzer 2 (ihm ist lt. Tabelle DEF zugeordnet):
1,ABC,DEF
2,DEF,ABC
3,DEF,GHI

Benutzer 3 (ihm ist lt. Tabelle DEF und GHI zugeordnet)
alle, weil überalll mind. DEF oder GHI drin vorkommt


Verständlich? Da ein Benutzer mehrere tausend Codes haben kann, will
ich ja nicht erst bei jedem User mit ner While-Schleife tausend mal mit
ner einzelnen Select-Abfrage a la "SELECT id FROM table2 WHERE code =3D
code_a OR code =3D code_b" in den Benutzerrechte-Table reinspringen und
gucken, ob es eine Zuordnung gibt. Das wären für jede Abfrage
tausende von extra-Queries in ner While-Schleife.

Hat jemand rat?
Peter.

Re: Etwas "kompliziertere?" Abfrage

am 20.09.2006 17:19:59 von Thomas Rachel

Peter Stoss wrote:

> Verständlich? Da ein Benutzer mehrere tausend Codes haben kann, will
> ich ja nicht erst bei jedem User mit ner While-Schleife tausend mal mit
> ner einzelnen Select-Abfrage a la "SELECT id FROM table2 WHERE code =
> code_a OR code = code_b" in den Benutzerrechte-Table reinspringen und
> gucken, ob es eine Zuordnung gibt.

Das ist auch nicht Sinn der Sache. Dafür gibt es in einem relationalen DBMS
ja auch die Möglichkeit, Tabellen zu verknüpfen (JOIN).

In diesem Fall sind Tabellen 1 und 2 mit dem Feld id und 2 mit 3 über die
Codes verbunden.

Somit gilt:

SELECT code_a, code_b
FROM user
JOIN permissions p ON user.id=p.benutzer
JOIN codes ON p.code=codes.code_a OR p.code=codes.code_b
WHERE user.name='irgendwer'

Warum das so ist, verrät Dir das Handbuch unter http://dev.mysql.com/, und
auch, daß Du, um diese Abfrage halbwegs performant hinzubekommen, Indizes
anlegen mußt.

Allerdings ist es (zumindest in 4.0) so, daß die OR-Bedingung in dem Join
zwischen Tabelle 2 und 3 nicht ausschließlich über Indizes augelöst werden
kann, d.h. das könnte etwas zeitintensiv werden.

Abhilfe: Wandle Tabelle 3 um nach folgender Maßgabe (sofern das die
drumrumliegende Anwendung zuläßt):

Spalten: id,id2,ab,code
Somit wird aus
1,ABC,DEF
2,DEF,ABC
3,DEF,GHI
4,GHI,ABC

die Tabelle

1,1,a,ABC
2,1,b,DEF
3,2,a,DEF
4,2,b,ABC
5,3,a,DEF
6,3,b,GHI
7,4,a,GHI
8,4,b,ABC

was allerdings an dem Query oben noch eine Änderung erfordert.


Thomas
--
Eine Schraube ohne Nagel ist ein Gewinde.