• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

Tabellen verknüpfen / Daten automatisch eintragen

Hallo zusammen,

gibt es die Möglichkeit das eine Tabelle ein bestimmtes Feld aus verschiedenen Datensätzen mit einer bestimmten Vorgabe einer anderen Tabelle der selben Datenbank ausliest und in ein Feld eines Datensatzes einträgt.

Bsp: Tabelle Serie soll alle Felder Storyname aus der Tabelle Serie mit dem selben Seriennamen in das Feld Serienteile eintragen.

Alternativ könnte ich mir auch vorstellen das die Storyteile die zur Serie gehören in einer Übersicht der Serien auf der Website aufgelistet werden.
 
Werbung:
Mich irritiert der Begriff "Tabelle soll". Eine Tabelle macht nichts. Sie dient nur dazu von dir gespeicherte Daten bereitzustellen, nicht diese für dich zu sammeln.

Ich vermute mal, dass Du eigentlich eine Ausgabe erreichen willst die Inhalte aus 2 Tabellen beinhaltet. Anhand deines Beispiels wäre das dann:
Code:
SELECT Storyname FROM Serie WHERE Serienname = 'A-Team'
 
Hallo,


vermutlich hast Du mich verstanden auch wenn mir der Code zu kurz erscheint.

Ich habe eine Tabelle in der die Serien aufgelistet werden (aus Tabelle: Serien)
ich möchte in die einzelnen Tabelleneinträge dann eine Liste ausgeben in der die Storys (aus Tabelle: Story) ausgegeben werden.

Natürlich sollen dabei immer nur die Storys aufgelistet werden die zur Serie gehören.


Ich hatte nun den Gedanken (die anfänglich Frage vor der Alternative) das ich hier vielleicht eine Verknüpfung der Tabellen bzw. der Storys mit den Serien erstellen könnte. Was möglicherweise das ganze vereinfacht.
 
Werbung:
Theorie:
Code:
SELECT *
FROM Stories st, Serien s
WHERE st.serienname = s.serienname

Praktisch solltest Du jedoch mit IDs arbeiten. Leider hast Du nicht geschrieben wie deine Tabellen aufgebaut sind, daher weiß ich nicht, ob Du solche bereits hast. Mit IDs würde MySQL nur einen Zahlenvergleich machen müssen, was performanter und für dich auch flexibler ist. Wenn Du IDs hast, sähe es beispielsweise so aus:

Code:
SELECT *
FROM Stories st, Serien s
WHERE st.serienid = s.serienid
 
Ich erinnere mich, daß Du die Diskussion über die Datenstruktur abgebrochen hast. Deine jetzige Frage zeigt ganz klar, daß Du besser noch ein bisserl weiter gegrübelt hättest. Du hast die Regeln der Normalisierung nicht angewendet.
 
Theorie:
Code:
SELECT *
FROM Stories st, Serien s
WHERE st.serienname = s.serienname

Praktisch solltest Du jedoch mit IDs arbeiten. Leider hast Du nicht geschrieben wie deine Tabellen aufgebaut sind, daher weiß ich nicht, ob Du solche bereits hast. Mit IDs würde MySQL nur einen Zahlenvergleich machen müssen, was performanter und für dich auch flexibler ist. Wenn Du IDs hast, sähe es beispielsweise so aus:

Code:
SELECT *
FROM Stories st, Serien s
WHERE st.serienid = s.serienid

Ich habe nun hier IDs eingeführt

Code:
SELECT * FROM Story st, Storyserien s WHERE st.SerienID = s.SerienID

doch da bei allen Serien alle Storys aufgelistet werden. Klappt der Vergleich wohl nicht ganz. Ich vermute das st und s stellvertretend für etwas stehen sollte.
Doch für was. Verglichen wird ja SerienID in den Tabellen Story und Storyserien.
 
Werbung:
Ich erinnere mich, daß Du die Diskussion über die Datenstruktur abgebrochen hast. Deine jetzige Frage zeigt ganz klar, daß Du besser noch ein bisserl weiter gegrübelt hättest. Du hast die Regeln der Normalisierung nicht angewendet.

Ich habe dort die Tour nicht mit Vor und Zurück gelöst sondern so wie auch die Navigation aufgebaut ist.
Die Storynummern innerhalb der Serien werden so getrennt nach FSK16 und FSK18 getrennt aufgebaut. Hinter der Nummer liegen dann die Links mit der URL die im Index.php für das includieren gebraucht werden.
 
Ich habe nun hier IDs eingeführt

Code:
SELECT * FROM Story st, Storyserien s WHERE st.SerienID = s.SerienID

doch da bei allen Serien alle Storys aufgelistet werden. Klappt der Vergleich wohl nicht ganz. Ich vermute das st und s stellvertretend für etwas stehen sollte.
Doch für was. Verglichen wird ja SerienID in den Tabellen Story und Storyserien.

Informiere dich über MySQL-Aliase, dann weißt Du auch was st und s in diesem Statement machen. Nein, das ist keine Funktion und keine Zauberei, vereinfacht nur das Schreiben von Statements.

Und zu deiner Frage: natürlich liefert dieses Statement eine Liste aller Stories in allen Serien aus. Wenn Du es auf eine Serie beschränken willst, ergänze eine WHERE-Bedingung:
Code:
SELECT * FROM Story st, Storyserien s WHERE st.SerienID = s.SerienID AND st.SerienID = '1'

Oder

Code:
SELECT * FROM Story st, Storyserien s WHERE st.SerienID = s.SerienID AND st.Serienname = 'A-Team'

Wenn Du etwas anderes willst, formuliere es und schreib es es genau so im Statement nieder.
 
Ich hätte vermutet das der Code
Code:
SELECT * FROM Story, Storyserien WHERE Story.SerienID = Storyserien.SerienID
heißen muss damit beide SerienID den selben Wert haben.
Und gehe wenn ich meinem Buch zu sql glauben darf so muss dieser Code auch der richtige sein. (mit der einzigen Ausnahme das statt * nur die Felder ausgewählt werden die auch verwendet werden.)

Einen Zusatz zum Feldnamen gibt es nicht.

Es gibt in den Storys aktuell 7 Serien.

die Serien mit der selben SerienID (1, 2, 3, 4, 5, 6 oder 7) sollen also verglichen werden.
Und dann werden die Storynamen der Serie mit der selben SerienID ausgegeben.
 
Zuletzt bearbeitet:
Werbung:
Ja, da vermutest Du auch richtig. Das ist die lange Schreibweise von dem was ich dir oben geschrieben hatte. Ist inhaltlich das Selbe.

Und: die IDs haben dadurch nicht den selben Wert sondern die Datensätze der IDs mit den selben Werten werden zusammengeführt.

Eine Frage konnte ich aber auch aus deinem letzten Beitrag nicht herauslesen.
 
Das ganze geht auch mit einem left join der evtl. effektiver ist

Code:
SELECT * FROM Storyserien s LEFT JOIN Story st USING(SerienID)

als erste bei einem join sollte die kleinere Tabelle stehen.
 
Ja, da vermutest Du auch richtig. Das ist die lange Schreibweise von dem was ich dir oben geschrieben hatte. Ist inhaltlich das Selbe.

Und: die IDs haben dadurch nicht den selben Wert sondern die Datensätze der IDs mit den selben Werten werden zusammengeführt.

Eine Frage konnte ich aber auch aus deinem letzten Beitrag nicht herauslesen.


Ach so, das ist die lange Schreibweise.
Ich denke ich verstehe was Du mit dem zusammenführen der IDs meinst.
Doch mit dem vollständigen Code sollte dann doch nur das ausgegeben werden wo die IDs in Story mit der ID in Storyserie übereinstimmt?
Doch irgendwo muss der Vergleich nicht auf die Ausgabe übergeben werden. Nur warum?
Ich finde den Fehler nicht warum das Ergebnis nicht ist wie ich es erwarte.

Code:
$storys = mysql_query("SELECT Storyname FROM Story, Storyserien WHERE Story.SerienID = Storyserien.SerienID");

        echo '<h3>Storys dieser Serie:</h3>';

while($rowstory = mysql_fetch_object($storys))
{

        echo '<li>' ,$rowstory->Storyname, '</li>';
};   // ende while
 
Zuletzt bearbeitet:
Werbung:
Btw. würde ich das Datenbankmodell weiter normalisieren. Die Spalte "Serie" solltest Du als Integer definieren und in einer zweiten Tabelle "Serien" bestehend aus "Serie" (Int, PK) und "Serientitel" (varchar) die einzelnen Serien definieren. Dadurch hast Du später auch mehr Möglichkeiten und kannst die Daten auch performanter auslesen.

Aber Serie ist keine Zahl sondern der Titel. Die Nummer habe inzwischen ja mit SerienID eingeführt. Und ist der ist ein Int.
Da man die Storys auch einzeln aufrufen kann ohne die Serie zu nutzen. Und es darüber hinaus auch Einzelstorys. Aber nun da ich die ID habe könnte ich die Serie (also den Titel) und ggf. SerienNr (die Nummer der Story innerhalb der Serie) rauslöschen. Doch dann muss ich für die Storys immer zwei Tabellen bearbeiten. So nur eine. Denn Serie beinhaltet nur die Infos die alle Storys der jeweiligen Serie gemeinsam haben.

Und wo ich gerade dabei bin und mich mit Performanz versuche zu beschäftigen mal die Frage was ihr von den Index's haltet die ich z.B. in der Tabelle Story habe.
 

Anhänge

  • tabellen undis.jpg
    tabellen undis.jpg
    92,4 KB · Aufrufe: 2
Und wo ich gerade dabei bin und mich mit Performanz versuche zu beschäftigen mal die Frage was ihr von den Index's haltet die ich z.B. in der Tabelle Story habe.
Das ist Unsinn, du darfst nicht auf alle Felder einen Index setzen. Der Index ist doppelt so gross wie deine Daten, d.h. der Index macht die Abfrage langsamer.
 
Das ist Unsinn, du darfst nicht auf alle Felder einen Index setzen. Der Index ist doppelt so gross wie deine Daten, d.h. der Index macht die Abfrage langsamer.

also alle Felder habe ich garnicht auf Index gesetzt. Ich hatte gelesen das durch einen Index schneller und besser nach einem Eintrag gesucht werden kann. Deshalb habe ich einige Felder der Tabelle auf Index gesetzt. Vergleiche selber es sind nicht alle. Aber ich werde das dann natürlich wieder ändern.
Welche Felder machen den naturgemäß ausser einer ID oder einer laufenden Nummer sinn?
 

Anhänge

  • tabellen undis.jpg
    tabellen undis.jpg
    92,4 KB · Aufrufe: 3
  • Tabellenstruktur - Story.jpg
    Tabellenstruktur - Story.jpg
    81,8 KB · Aufrufe: 4
Werbung:
also alle Felder habe ich garnicht auf Index gesetzt. Ich hatte gelesen das durch einen Index schneller und besser nach einem Eintrag gesucht werden kann. Deshalb habe ich einige Felder der Tabelle auf Index gesetzt. Vergleiche selber es sind nicht alle. Aber ich werde das dann natürlich wieder ändern.
Welche Felder machen den naturgemäß ausser einer ID oder einer laufenden Nummer sinn?
Erstmal die, nach denen gesucht, sortiert oder mit denen Tabellen verknüpft werden. Aber weniger ist auf jeden Fall mehr. Der Sinn des Index ist ja, dass mysql nicht die ganze Tabelle durchsuchen muss, in deinem Fall ist der Index viel größer als die Tabelle, folglich hast du genau das gegenteil erreicht.

Rausfinden, wie eine Tabelle am besten indiziert wird, ist nicht so einfach und richtet sich natürlich auch nach den Abfragen. Da hilft den EXPLAIN weiter. Ein sinnvolleres vorgehen ist also erstmal wenig oder keinen Index zu setzen (ausser primary) und dann bei den Abfragen mit Explain rausfinden, wann welche Indizes benutzt werden.

Noch ein Wort zum Tabellendesign: erstellt und ueberarbeitet klingen für mich nach Datum, daher wäre es hier besser DateTime zu benutzen, dann kannst du dir vermutlich auch das Feld neu sparen (und bist danach auch flexibler, da du dann den Status "neu" Anhand eines Zeitintervalls bestimmen könntest).

Evtl. ist es auch sinnvoll, die Texte, wie z.b. Kommentare, beschreibung in eine separate Tabelle zu verlegen, da naturgemäß ein Fulltext Index nicht sehr performant ist.

Und noch ein kleiner Tipp, du scheinst zu denken, dass die Längenangaben bei den Zahlenfelder (int, tinyint) eine Rolle für die Größe spielen, das ist falsch das ist nur die Anzeigenlänge, lass sie einfach auf die Größe die mysqladmin vorschlägt.

Dann hast du vermutlich viel redundanz in der Tabelle, zumindest ist nicht ersichtlich, warum du soviele mit "Nummer" bezeichnete Felder hast. Und statt Nummer, verwende lieber den Begriff ID, das ist gebräuchlicher. Dabei fällt mir auf, im Index steht ein Feld SerienID in der Struktur taucht diese aber gar nicht auf.
 
Erstmal die, nach denen gesucht, sortiert oder mit denen Tabellen verknüpft werden. Aber weniger ist auf jeden Fall mehr. Der Sinn des Index ist ja, dass mysql nicht die ganze Tabelle durchsuchen muss, in deinem Fall ist der Index viel größer als die Tabelle, folglich hast du genau das gegenteil erreicht.

Rausfinden, wie eine Tabelle am besten indiziert wird, ist nicht so einfach und richtet sich natürlich auch nach den Abfragen. Da hilft den EXPLAIN weiter. Ein sinnvolleres vorgehen ist also erstmal wenig oder keinen Index zu setzen (ausser primary) und dann bei den Abfragen mit Explain rausfinden, wann welche Indizes benutzt werden.

Lasse ich EXPLAIN auf meinem PC laufen?
Denn mein Server steht nicht bei mir. Und ich bin nicht sicher ob ich dies Programm dort installieren könnte.

Noch ein Wort zum Tabellendesign: erstellt und ueberarbeitet klingen für mich nach Datum, daher wäre es hier besser DateTime zu benutzen, dann kannst du dir vermutlich auch das Feld neu sparen (und bist danach auch flexibler, da du dann den Status "neu" Anhand eines Zeitintervalls bestimmen könntest).

Evtl. ist es auch sinnvoll, die Texte, wie z.b. Kommentare, beschreibung in eine separate Tabelle zu verlegen, da naturgemäß ein Fulltext Index nicht sehr performant ist.

Die Fulltext Index kann ich auch wegnehmen. Ich habe inzwischen festgestellt das ich diese nicht brauchen würde. Es gibt keine Abfragen danach.
Die Felder ueberarbeitet und erstellt sind Felder vom Typ Jahr weil ich nur das Jahr kenne. Und keinen genauen Zeitpunkt. Zumindest vor 2010 nicht mehr.
Und auch nur das Jahr angezeigt wird.

Und noch ein kleiner Tipp, du scheinst zu denken, dass die Längenangaben bei den Zahlenfelder (int, tinyint) eine Rolle für die Größe spielen, das ist falsch das ist nur die Anzeigenlänge, lass sie einfach auf die Größe die mysqladmin vorschlägt.

Ich bin nicht sicher ob ich verstanden habe was Du mit Größe meinst. Ich habe die Felder so eingestellt weil ich aktuell die Anzeigelänge von 2 Zeichen bei den Nummern oder IDs benötige.

Dann hast du vermutlich viel redundanz in der Tabelle, zumindest ist nicht ersichtlich, warum du soviele mit "Nummer" bezeichnete Felder hast. Und statt Nummer, verwende lieber den Begriff ID, das ist gebräuchlicher. Dabei fällt mir auf, im Index steht ein Feld SerienID in der Struktur taucht diese aber gar nicht auf.

Es handelt sich dabei um laufende Nummern. Eine echte ID die zwei Tabellen mit einander verknüpft ist nun im Zusammenhang mit Story und Serie erst entstanden.
Die Nummern:
StoryNr. = laufende Nummer dem erstellen nach.
SerienID = laufende Nummer und verknüpfung der Serie
SerienNr = Nummer der Sorie in der Serie

weitere Nummern gibt es in dieser Tabelle nicht.

Nun sind nur noch folgende über. Die auch in Abfragen auftauchen. (so aus dem Kopf)

BTREEJaNeinStorynummer67A
BTREENeinNeinStoryname0A
BTREENeinNeinSerieNr0A
BTREENeinNeinSerienID0A

PRIMARY

Storyname

SerieNr

SerienID
 
Zuletzt bearbeitet:
Das ganze geht auch mit einem left join der evtl. effektiver ist

Code:
SELECT * FROM Storyserien s LEFT JOIN Story st USING(SerienID)

als erste bei einem join sollte die kleinere Tabelle stehen.

Das hatte ich auch probiert doch hatte ich das selbe Problem.
Deshalb bin ich zur beschrieben Code zurück gekehrt und stelle meine Frage warum dies nicht funktioniert http://www.html.de/datenbanken-z-b-...daten-automatisch-eintragen-2.html#post301995

Und wenn ich meine Zeile erweitere
Code:
$storys = mysql_query("SELECT Storyname FROM Story, Storyserien WHERE Story.SerienID = Storyserien.SerienID [B]AND Storyserien.SerienID = '1'"[/B]);

        echo '<h3>Storys dieser Serie:</h3>';

while($rowstory = mysql_fetch_object($storys))
{

        echo '<li>' ,$rowstory->Storyname, '</li>';
};   // ende while

Dann kommt in diesem Fall nur die Serie mit ID = 1 heraus. Aber ich möchte natürlich das die jeweilig entsprechende Liste aufkommt.
Eine if-Anweisung wird es ja wohl kaum sein. Denn wenn ich das so verstanden habe geht das dies mal mit der Verknüpfung "ist gleich". In der die ID-Werte verglichen werden und bei gleichem Wert ausgegeben werden.
 
Zuletzt bearbeitet:
Werbung:
Code:
SELECT Storyname
FROM Story, Storyserien
WHERE Story.SerienID = Storyserien.SerienID
  AND Storyserien.SerienID = '1'

Das müsste theoretisch hinhauen, wenn auch Theta-Style-Joins nicht mehr wirklich empfohlen werden.

Ich weiß nicht genau, wie man da am besten rangeht. Vielleicht könntest du mal die Daten zeigen?
 
Zurück
Oben