n:m-Beziehung
Dr. Brettermeier
- datenbank
Hallo, liebes Forum,
mein Problem ist folgendes:
Ich habe eine n:m-Beziehung in meiner Datenbank, da in jedem Spielfilm mehrere Darsteller agieren und jeder Darsteller in mehreren Filmen auftreten kann.
Mein Ergebnis mit folgender Anfrage:
<?php
$query="select Titel,Name from darsteller,filme,rel_filme_darsteller where
filme.filmID=rel_filme_darsteller.filmID and rel_filme_darsteller.darstellerID=
darsteller.darstellerID";
$result=mysql_query($query);
while ($row=mysql_fetch_array($result,MYSQL_ASSOC)) {
echo $row['Titel'];
echo $row['Name'];
}
?>
sieht so aus :
Filmtitel1 Darstellername1
Filmtitel1 Darstellername2
Ich will aber folgendes ;
Filmtitel Darstellername1
Darsteleername2
Mit reinem MYSQL habe ich keine Lösung gefunden, was an meinem Anfängerstatus liegen mag.
Weiß jemand eine probate Lösung für mein kleines Problemchen?
Hallo,
Ich bin in Datenbanksachen leider auch recht schlecht ( muss mir da mal Wissen anlesen)
Aber geht das was du vorhast nicht mit Group by filmtitel??
Habe mal so ein ähnliches Problem gehabt und es so gelöst.
sven
Hi,
Mit reinem MYSQL habe ich keine Lösung gefunden, was an meinem Anfängerstatus liegen mag.
nein, in SQL wäre so etwas nur mit erheblichem Aufwand lösbar (und vermutlich auch nur mit einem DBMS, welches Subselects beherrscht). Mache das in PHP, indem Du feststellst, ob sich der aktuell auszugebende Filmtitel von dem zuvor ausgegebenen unterscheidet. GROUP BY (s. svens Antwort) oder ORDER BY sind hierbei hilfreich.
Cheatah
Halihallo Cheatah
nein, in SQL wäre so etwas nur mit erheblichem Aufwand lösbar (und vermutlich auch nur mit einem DBMS, welches Subselects beherrscht). Mache das in PHP, indem Du feststellst, ob sich der aktuell auszugebende Filmtitel von dem zuvor ausgegebenen unterscheidet. GROUP BY (s. svens Antwort) oder ORDER BY sind hierbei hilfreich.
Es ist IMHO gar nicht möglich, da das von Dr. Brettermeier gewünschte Result-Set einer
NF2 (Non First Normal Form) Tabelle entspräche, welche es niemals geben kann
(Resultsets, wie auch Tabellen der wohl meisten RDBMS erlauben keine mehrwertigen
Attribute [mengenartige Attribute]).
Der Umweg über mehrere Queries oder einer programmiertechnischen Umsetzung ist IMHO die
einzige Lösung (zumindest um eine Plattform-/Programmunabhängige Lösung zu erstellen).
Viele Grüsse
Philipp
Hallo Philipp,
Es ist IMHO gar nicht möglich, da das von Dr. Brettermeier gewünschte Result-Set einer
NF2 (Non First Normal Form) Tabelle entspräche, welche es niemals geben kann
(Resultsets, wie auch Tabellen der wohl meisten RDBMS erlauben keine mehrwertigen
Attribute [mengenartige Attribute]).
Das verstehe ich nicht, meinst du, dass ich nicht "richtig" Normalisiert habe ?
Gruß
Dr. B
Halihallo <vorname>
[...]
Das verstehe ich nicht, meinst du, dass ich nicht "richtig" Normalisiert habe ?
Nein. Nur das von dir gewünschte Format
Filmtitel Darstellername1
Darsteleername2
entspräche nicht der normalisierten Form. Abgebildet würde dies etwa folgendes ergeben:
Filmtitel => ['Darstellername1', 'Darstellername2']
dies ist leider in SQL nicht abzubilden, da jedes Attribut lediglich einen und nur einen
Wert annehmen darf.
Falls du nach Filmtitel gruppierst (was du oben andeutest), werden die einzelnen Werte
der korrespondierenden Attribute zusammengezogen, jedoch kann man diese nicht mehr
eindeutig "adressieren/ausgeben". Die einzige Möglichkeit, welche SQL zur Behandlung
solcher anbietet, sind die Aggregatsfunktionen und diese liefern eben nur einen Wert (z.
B. die Summe, den Durchschnitt oder die Anzahl passender/korrespondierender
Attributwerte).
Wenn du nach Filmtitel gruppierst, jedoch die einzelnen Attributwerte (Darstellernamen)
auch ausgeben möchtest, ist
Filmtitel1 Darstellername1
Filmtitel1 Darstellername2
die einzig mögliche Notation, da du dann zu jedem Filmtitel zwar mehrere Darstellernamen
hast, jedoch in den einzelnen Datensätzen nur jeweils einen Attibutwert hast (das ist
der Grund, warum Filmtitel dann notgedrungen [weil eben mehrwertige Attribute nicht
möglich sind] mehrmals auf der linken Seite erscheint).
Etwas verständlicher ausgedrückt: Das Ergebnis (Ergebnisrelation) ist eine Tabelle,
welche in jeder Zelle nur einen Wert haben kann. Da du zu jedem Darsteller auch einen
Filmtitel hast, wird dieser auch ausgegeben [nicht wie von dir preferiert, unterdrückt].
Die Datenbank "merkt" nicht, dass der Filmtitel von einem Record weiter oben der selbe
ist; denn das ist/wäre gar nicht sinnvoll (da dies eine Art von NF2 Tabelle wäre, die es
eben nach der 1. Normalenform nicht geben soll).
Viele Grüsse
Philipp
Hi,
Es ist IMHO gar nicht möglich, da das von Dr. Brettermeier gewünschte Result-Set einer
NF2 (Non First Normal Form) Tabelle entspräche, welche es niemals geben kann
die erste Spalte kann in allen Zeilen nach der ersten schlichtweg leer sein. Es müsste lösbar sein, wenn auch überproportional kompliziert.
Der Umweg über mehrere Queries oder einer programmiertechnischen Umsetzung ist IMHO die
einzige Lösung (zumindest um eine Plattform-/Programmunabhängige Lösung zu erstellen).
Mehrere Queries halte ich für den am ehesten zu vermeidenden Weg - nicht nur, dass im zweiten Query die Berechnung des ersten Queries (indirekt) erneut erfolgen müsste (es sei denn, Du holst erst nur den/die Filmtitel und dann den Rest); es sind vor allem zwei Roundtrips, von denen einer unnötig ist. Und wie wir alle wissen, ist der Roundtrip an sich das teuerste an der Geschichte... oder man hat etwas gründlich falsch gemacht ;-)
Die Lösung in der umgebenden Programmlogik ist hingegen eher trivial. Da es zudem problematisch ist, die Darstellung bereits in der Abfragelogik zu diktieren (mehr oder weniger), ist dies IMHO sogar der einzig richtige Weg. Man kann es z.B. auch per XSL lösen.
Cheatah
Danke für die antworten.
Ich habe es jetzt einfach mal so gemacht...
...
$wahr=TRUE;
while ($row=mysql_fetch_array($result,MYSQL_ASSOC)) {
if ($wahr) {
echo $row['Titel'];
echo $row['Nachname'];
$wahr=FALSE;}
else {
echo $row['Nachname'];}
}
Hi,
Ich habe es jetzt einfach mal so gemacht...
danke! Das machen leider viel zu wenige, ihre Lösung noch zu posten.
$wahr=TRUE;
[...]
Das funktioniert natürlich nur, wenn Du höchstens einen Filmtitel erwartest. Bei mehreren merke Dir einfach den jeweiligen Titel und vergleiche innerhalb der while-Schleife.
Cheatah