Dr. Brettermeier: n:m-Beziehung

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?

  1. 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

  2. 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

    --
    X-Will-Answer-Email: No
    1. 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

      1. 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

        1. 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

      2. 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

        --
        X-Will-Answer-Email: No
  3. 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'];}
    }

    1. 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

      --
      X-Will-Answer-Email: No