Datenbankdesign ENUM, SET

Datenbankdesign ENUM, SET

am 07.11.2007 15:07:31 von steffen horst

Hallo,

ich hatte bis vor einigen Tagen eine Tabelle mit drei Feldern: INT,
ENUM und SET, also z.B.:

id INT
fragesteller ENUM (person_A1, person_A2, person_A3)
antwortende SET (person_A1, person_A2, person_A3)


Da es mehrere solcher Personengruppen (Gruppe_A: person_A1, person_A2,
person_A3; Gruppe_B: person_B1, person_B2, ...) gab, hab ich für jede
eine solche Tabelle angelegt, also z.B.:

TABLE gruppe_A
id INT
fragesteller ENUM (person_A1, person_A2, person_A3)
antwortende SET (person_A1, person_A2, person_A3)

TABLE gruppe_B
id INT
fragesteller ENUM (person_B1, person_B2, person_B3)
antwortende SET (person_B1, person_B2, person_B3)


Die Anfrage für alle Einträge war einfach:

SELECT id, fragesteller, antwortende
FROM gruppe_A


Nun möchte ich nicht ständig neue Tabellen für neue Gruppen anlegen,
sondern alle Einträge in einer Tabelle ablegen. Das ist offensichtlich
zunächst unmöglich, da ich nicht alle Personen in SET und ENUM
aufnehmen kann. Das heißt, ich benötige schon vier Tabellen:

TABLE frage
id INT
fragesteller_id INT
gruppe_id INT // da alle Fragen nun in eine Tabelle kommen

TABLE antwort
frage_id INT
person_id INT

TABLE person
id INT
name VARCHAR

TABLE gruppe
id INT
name VARCHAR


Nun kann ich also über gruppe_id die Fragen den Gruppen zuordnen und
über frage_id die Antworten den Fragen.


Die vorher so leichte Anfrage

SELECT id, fragesteller, antwortede
FROM tabelle1

ist nun überaus aufwändig! Jetzt benötige ich zunächst alle Fragen
einer Gruppe, also etwa so:

SELECT id, name
FROM frage, person
WHERE gruppe_id = 0
AND fragesteller_id = person.id

Und dann muss ich zu jedem dieser Anfrageergebnisse (mit $i = id) eine
weitere Anfrage ausführen:

SELECT name
FROM antwort, person
WHERE frage_id = $i
AND antwort.person_id = person.id


Das heißt, was vorher eine Anfrage war, sind nun (1+n) Anfragen (mit n
als Anzahl der Fragen einer Gruppe).

Gibt es nicht ein besseres Design als dieses??


Eine (ebenfalls seltsame) Möglichkeit, die mir spontan einfällt ist
diese:

Angenommen, es gibt nicht mehr als 10 Personen in einer Gruppe. Dann
könnte man das Problem eventuell in etwa so lösen:

TABLE frage
id INT
gruppe_id INT
fragesteller_id INT
antwortende BIT(10)

TABLE person
id INT
mitglieds_nr INT (1-10)
gruppe_id INT
name VARCHAR

TABLE gruppe
id INT
name VARCHAR


SELECT id, name, antwortende
FROM frage, person
WHERE frage.gruppe_id = 0
AND fragesteller_id = person.id


Um die Mitgliedsnamen aufzulösen, benötigt man natürlich dann noch
eine weitere Anfrage. Oder gibts da noch irgendwas SINNVOLLES?

Normalisiert ist nur der aktuelle Stand, aber der erzwingt einen
Haufen mehr Anfragen.

Danke für jegliche Hilfen, steffen

Re: Datenbankdesign ENUM, SET

am 07.11.2007 15:35:42 von Christian Kirsch

Am 07.11.2007 15:07 schrieb steffen horst:
>
> Nun möchte ich nicht ständig neue Tabellen für neue Gruppen anlegen,
> sondern alle Einträge in einer Tabelle ablegen. Das ist offensichtlich
> zunächst unmöglich, da ich nicht alle Personen in SET und ENUM
> aufnehmen kann. Das heißt, ich benötige schon vier Tabellen:
>
> TABLE frage
> id INT
> fragesteller_id INT
> gruppe_id INT // da alle Fragen nun in eine Tabelle kommen
>
> TABLE antwort
> frage_id INT
> person_id INT
>
> TABLE person
> id INT
> name VARCHAR
>
> TABLE gruppe
> id INT
> name VARCHAR
>
>
> Nun kann ich also über gruppe_id die Fragen den Gruppen zuordnen und
> über frage_id die Antworten den Fragen.
>
>
> Die vorher so leichte Anfrage
>
> SELECT id, fragesteller, antwortede
> FROM tabelle1
>
> ist nun überaus aufwändig! Jetzt benötige ich zunächst alle Fragen
> einer Gruppe, also etwa so:
>
> SELECT id, name
> FROM frage, person
> WHERE gruppe_id = 0
> AND fragesteller_id = person.id
>
> Und dann muss ich zu jedem dieser Anfrageergebnisse (mit $i = id) eine
> weitere Anfrage ausführen:
>
> SELECT name
> FROM antwort, person
> WHERE frage_id = $i
> AND antwort.person_id = person.id
>

SELECT p.name from person p
JOIN adressen a ON p.id = a.person_id
WHERE a.frage_id IN
(SELECT p.id FROM person p
JOIN frage f ON p.id = f.fragesteller_id
WHERE f.gruppe_id = 0)

Nicht getestet, aber im Prinzip könnte es so gehen.
>
> Das heißt, was vorher eine Anfrage war, sind nun (1+n) Anfragen (mit n
> als Anzahl der Fragen einer Gruppe).
>

Nicht unbedingt.

> Gibt es nicht ein besseres Design als dieses??
>
Vielleicht.

--
Christian

Re: Datenbankdesign ENUM, SET

am 07.11.2007 18:03:49 von Claus Reibenstein

steffen horst schrieb:

> Die vorher so leichte Anfrage
>
> SELECT id, fragesteller, antwortede
> FROM tabelle1
>
> ist nun überaus aufwändig! Jetzt benötige ich zunächst alle Fragen
> einer Gruppe, also etwa so:
>
> SELECT id, name
> FROM frage, person
> WHERE gruppe_id = 0
> AND fragesteller_id = person.id
>
> Und dann muss ich zu jedem dieser Anfrageergebnisse (mit $i = id) eine
> weitere Anfrage ausführen:
>
> SELECT name
> FROM antwort, person
> WHERE frage_id = $i
> AND antwort.person_id = person.id

Das geht auch in _einer_ Anfrage (ungetestet):

SELECT f.id, p1.name AS fragesteller, p2.name AS antwortende
FROM frage f, antwort a, person p1, person p2
WHERE f.gruppe_id = 0
AND f.fragesteller_id = p1.id
AND a.frage_id = f.id
AND a.person_id = p2.id

Gruß. Claus