Film mit mehreren Genres

AlexMineiro

Grünschnabel
Hi,

hab da ein kleines Mysql Problem. Ich versuche meine eigene DVD Datenbank zu machen da mir alle fertigen scripts nicht gefallen. Mein Problem besteht darin das ich nun bei Genre gerne mehrere für einen Film machen möchte. Zum Beispiel:

Film = Herr der Ringe - Die Gefährten
Genre = Abenteuer, Fantasy

Ich bekomme es bisher nur hin das er mir nur 1 Genre anzeigt.

Habe 3 Tabellen gemacht

1. Tabelle = Film ( ID, Filmtitel, Medium, Inhalt, Genre )
2. Tabelle = FilmGenre (Film_ID, GenreName)
3. Tabelle = Genre ( ID, Name)

Verknüpft hab ich
- Tabelle1 mit Tabelle2 mit Film.ID + FilmGenre.Film_ID
- Tabelle2 mit Tabelle3 mit Filmgenre.Genre_ID + Genre.ID
- Tabelle 1 mit Tabelle 3 mit Film.Genre_ID + FilmGenre.Genre_Name

Nun müsste das ja dann so aussehen

Select * from 2.tabelle WHERE Film.ID = Filmgenre.Film_ID

oder mach ich da einen Denkfehler ?

Sollte dann in der Genre_ID in Tabelle dann stehen "Abenteuer, Fantasy".

Gruss
Alex
 
Zuletzt bearbeitet:
Okay, dein Ansatz mit den 3 Tabellen ist schon mal vernünftig..

Allerdings würde ich die Tabellen anders aufbauen:

Deine erste Tabelle "Film" sollte kein Attribut "Genre" haben.

Die Verbindung zu einem Genre stellst du über eine andere Tabelle her. Du hast das schon mit deiner zweiten Tabelle versucht, aber wir ändern die Tabellen jetzt ein wenig.

Schmeiss zuerst aus deiner ersten Tabelle das Attribut "Genre" raus:
Code:
1. Tabelle = Film ( ID, Filmtitel, Medium, Inhalt )
mehr brauchst du hier nicht.

In diese Tabelle speicherst du jetzt alle deine Filme..

Deine dritte Tabelle ist gut, lass die so:
Code:
3. Tabelle = Genre ( ID, Name)

Hier speicherst du jetzt alle Genres, die dir einfallen. Thriller, Fantasy, Western, Action.....

Mit deiner zweiten Tabelle stellst du jetzt die Verbindung zwischen Film und Genre her. Du findest, das ein Film mehrere Genres haben darf und das von einem Genre auch mehrere Filme sind. Also erstell diese Tabelle so:
Code:
2. Tabelle = FilmGenre (FID, GID)
FID ist die ID aus der Tabelle Film und GID die ID aus der Tabelle Genre.

Ich denke ein Beispiel hilft:

In Tabelle "Film" steht bisher dein einziger Film "Hancock":
Code:
ID, Filmtitel, Medium, Inhalt
1, "Hancock", "CD", "betrunkener Superheld...."

In Tabelle "Genre" stehen schon 5 Genres:
Code:
ID, Name
1, "Action"
2, "Drama"
3, "Horro"
4, "Comedy"
5, "Fantasy"

In Tabelle "FilmGenre" sagst du jetzt, dass du findest, das "Hancock" zu "Action" und zu "Comedy" gehört:
Code:
FID, GID
1, 1
1, 4

Fertig...

Du hast verschiedene Möglichkeiten die Daten wieder auszulesen.
Bspw. möchtest du jetzt wissen, zu welchen Genres "Hancock" gehört:
1) guck in Tabelle "Film" nach, welche ID der Film "Hancock" hat:

SQL:
SELECT id
FROM film
WHERE filmtitel = 'Hancock';

das wird dir in unserem Beispiel den Wert 1 liefern..


2) guck in Tabelle "FilmGenre" nach, welche Eintragungen du dort zu diesem Film gemacht hast

SQL:
SELECT gid
FROM `filmgenre`
WHERE fid = 1;

und das wird dir in unserem Beispiel die Werte 1 und 4 liefern..


3) guck für jede gid in Tabelle "Genre" nach, wie das Genre heißt:

SQL:
SELECT name
FROM `genre`
WHERE id = 1;

SQL:
SELECT name
FROM `genre`
WHERE id = 4;


Probiers mal aus...
 
Zuletzt bearbeitet von einem Moderator:
Hallo,
noch eine kleine Ergänzung zu turicos tollen und ausführlichen Erklärung:
Wenn du nur an den Genres eines bestimmten Films interessiert bist, dann kannst du die 3 Tabellen auch in einer Abfrage verknüpfen:
SQL:
SELECT 
    g.* 
FROM 
    film AS f 
    JOIN 
        filmgenre AS fg ON f.id = fg.fid
    JOIN 
        genre AS g ON g.id = fg.gid 
WHERE 
    f.filmtitel = 'Hancock'

Zur Namensgebung noch ein paar subjektive Anmerkungen:
- Tabellen-/Spaltennamen durchgängig klein und ggf. Wörter mit "_" trennen
- englische Bezeichnungen (allein vom Sprachgefühl schon) - aber das ist jedem selbst überlassen
- bei Tabellennamen sind Pluralformen logischer, da Tabellen i.d.R. mehr als einen Eintrag besitzen ;)
- Spaltennamen wie 'Filmtitel' sind "doppelt gemoppelt", da durch den Tabellennamen schon klar ist worauf sich der Titel bezieht

Schöne Grüße und einen schönen Sonntag,
Marvin
 
Hi,

so hab mal nun nach längerer Zeit mich wieder drangemacht und habs auch "fast" nun hinbekommen, jedoch ist noch eine kleinigkeit die ich beheben muss und zwar hab ich ein problem mit ner abfrage in einer While Schleife. Die Abfrage an sich wird richtig dargestellt jedoch nach der abfrage kommt dann in der Html Ausgabe kein Text mehr... wird wohl ein kleineres Problem sein aber ich hoffe jmd kann mir dabei helfen weil ich nun leider nicht mehr weiter weiss..

Folgender Quelltext

Code:
<?php $site = $_GET[site]; $title = $_GET[title]; $id = $_GET[id];
$abfrage = "SELECT * FROM film WHERE id = $id ";
$ergebnis = mysql_query($abfrage);
while($row = mysql_fetch_object($ergebnis))
{ echo "<div id='content_inhalt_header'>MOFDB &raquo; ".$site." &raquo; ".$title.$id."</div>
<div id='details_box'>
      <div id='details_box_header'>".$row->deutschertitel."</div>
 <table width='590' border='0' cellspacing='0' cellpadding='0'>
        <tr>
          <td width='160' class='details'><div id='details_box_cover'><img src='bilder/covers/".$row->cover.".jpg' width='140' height='198' border='0' alt='".$row->deutschertitel."' title='".$row->deutschertitel."' /></div></td>
          <td width='430' class='details'><table width='430' border='0' cellspacing='0' cellpadding='0'>
              <tr>
                <td class='details_links'>Originaltitel:</td>
                <td class='details_rechts'>".$row->originaltitel."</td>
              </tr>
              <tr>
                <td colspan='2' class='leer'></td>
              </tr>
              <tr>
                <td class='details_links'>Herstellungsland:</td>
                <td class='details_rechts'><a href='index.php?site=herstellungsland&amp;herstellungsland=".utf8_encode($row->herstellungsland)."'>".utf8_encode($row->herstellungsland)."</a></td>
              </tr>
              <tr>
                <td colspan='2' class='leer'></td>
              </tr>
              <tr>
                <td class='details_links'>Erscheinungsjahr:</td>
                <td class='details_rechts'><a href='index.php?site=erscheinungsjahr&amp;erscheinungsjahr=".utf8_encode($row->erscheinungsjahr)."'>".utf8_encode($row->erscheinungsjahr)."</a></td>
              </tr>
              <tr>
                <td colspan='2' class='leer'></td>
              </tr>
              <tr>
                <td class='details_links'>Genre(s):</td>
                <td class='details_rechts'>"; $id = $_GET[id]; $genre_abfrage = "SELECT genreid FROM filmgenre WHERE filmid = $id";
$genre_ergebnis = mysql_query($genre_abfrage);
while ($row = mysql_fetch_object($genre_ergebnis)){ 
$genre_abfrage_name = "SELECT * from genre WHERE id = $row->genreid" ;
$genre_abfrage_ergebnis = mysql_query($genre_abfrage_name);
while ($row = mysql_fetch_object($genre_abfrage_ergebnis)){
echo utf8_encode($row->name)."<br \>" ; } }; ; echo"</td>
              </tr>
              <tr>
                <td colspan='2' class='leer'></td>
              </tr>
              <tr>
                <td class='details_links'>Regie:</td>
                <td class='details_rechts'></td>
              </tr>
              <tr>
                <td colspan='2' class='leer'></td>
              </tr>
              <tr>
                <td class='details_links'>Sprache(n):</td>
                <td class='details_rechts'></td>
              </tr>
              <tr>
                <td colspan='2' class='leer'></td>
              </tr>
              <tr>
                <td class='details_links'>Untertitel:</td>
                <td class='details_rechts'></td>
              </tr>
              <tr>
                <td colspan='2' class='leer'></td>
              </tr>
              <tr>
                <td class='details_links'>Schauspieler:</td>
                <td class='details_rechts'>".$row->darsteller."</td>
              </tr>
              <tr>
                <td colspan='2' class='leer'></td>
              </tr>
			                <tr>
                <td colspan='2' class='leer'></td>
              </tr>
              <tr>
                <td class='details_links'>Medium:</td>
                <td class='details_rechts'><a href='index.php?site=medium&amp;medium=".utf8_encode($row->medium)."'>".utf8_encode($row->medium)."</a></td>
              </tr>
              <tr>
                <td colspan='2' class='leer'></td>
              </tr>
              <tr>
                <td class='details_links'>OFDB Wertung:</td>
                <td class='details_rechts'><img src='wertungsbalken.php?breite=100&hoehe=10&prozent=".$row->ofdbwertung."' alt='".$row->ofdbwertung." von 10' title='".$row->ofdbwertung." von 10' />&nbsp;&nbsp;".$row->ofdbwertung." von 10</td>
              </tr>
			   <tr>
                <td colspan='2' class='leer'></td>
              </tr>
            </table></td>
        </tr>
				 <tr>
                <td colspan='2' class='leer'></td>
              </tr>
        <tr>
          <td colspan='2' class='details_inhaltsangabe_header'>Inhaltsangabe:</td>
        </tr>
        <tr>
          <td colspan='2' class='details_inhaltsangabe_text'>".utf8_encode($row->inhaltsangabe)."</td>
        </tr>
      </table>
    </div>"; } ?>

Der Fehler liegt in dem kleinen Quelltext wo die Genre Abfrage reingebaut wurde
Code:
 <td class='details_rechts'>"; $id = $_GET[id]; $genre_abfrage = "SELECT genreid FROM filmgenre WHERE filmid = $id";
$genre_ergebnis = mysql_query($genre_abfrage);
while ($row = mysql_fetch_object($genre_ergebnis)){ 
$genre_abfrage_name = "SELECT * from genre WHERE id = $row->genreid" ;
$genre_abfrage_ergebnis = mysql_query($genre_abfrage_name);
while ($row = mysql_fetch_object($genre_abfrage_ergebnis)){
echo utf8_encode($row->name)."<br \>" ; } }; ; echo"</td>
 
Zuletzt bearbeitet:
Hi,

Du solltest keine Datenbankabfragen innerhalb von Schleifen machen (bei Dir auch noch doppelt geschachtelt). Beschäftige Dich mal mit JOINs.
Abgesehen davon, dass Dein Scriptaufbau ein wahrer Performancekiller ist, ist das auch noch ziemlich fehleranfällig, wie man bei Dir sehr schön sehen kann. Du überschreibst die Variable $row in beiden inneren Schleifen. Ob das schon das ganze Problem ist, weiß ich nicht. Ich habe ehrlich gesagt keine Lust, mich detailliert durch einen derart schlecht bis gar nicht formatierten Code zu wühlen.

LG
 
Ich schau mir den Code auch nicht an, aber ich habe das Problem "nicht normalisiert" folgendermaßen gelöst, dass ich Genres Buchstaben gegeben habe, zB

Herr der Ringe - ADF

A - Action
D - Drama
F - Fantasie

Das gleiche ließe sich auch über Binärkodierung machen und sagen, das erste Bit ist Comedy, das zweite Action, das dritte Drama etc.. Heisst also, bei 8 Genres hast Du alle Informationen in einem Byte und Du brauchst dann nur per Bitüberprüfung herausfinden, welche Genre gewählt sind.

01 11 00 00 - wäre dann wieder eine Herr der Ringe-Beschreibung, da Bit 2 (Action), Bit 3 (Drama) und Bit 4 (Fantasie) gesetzt sind.

mfg chmee
 
Hi,

kann man für den Hausgebrauch sicherlich so machen. Der Nachteil ist halt, dass Du Code und Datenbank ändern musst, wenn Du Genres hinzufügen willst.

LG
 
Ach naja, DB muss nicht geändert werden, wenn Du dem Genreeintrag genügend Platz gibst. Wenn Binär kodiert, naja, dann reichen wohl 16 oder 32 Bit für eine recht vollständige Beschreibung. Bei der Buchstabenkodierung ist es einfach 32stelliger Text. Für einen DBler ist das logischerweise zu fade. Da muss alles normalisiert sein ( wofür es ja auch hinreichend Gründe gibt ).

Und codeseitig ist es quasi auch nur ein Template/Array, dass für Genre-Anzeigen und -Speichern benutzt wird. ( Was man auch in MySQL lösen darf :D )

mfg chmee

**Nachtrag : Ich weiß, dass es in dieser Form Hausmannskost ist, aber ich habe mich Anfangs auch mit der Normalisierung schwer getan. Dagegen ist "meine Hausmannsidee" recht einfach zu verstehen und umzusetzen. Auch wenn sie bei größeren Projekten Probleme bei einer Umstrukturierung/Veränderung machen wird. Ohne Zweifel.
 
Zurück