Hannes E.: mySQL-Daten aus 3 Tabellen zusammenfügen

Hallo! Hätte da mal eine Frage.

Ich habe in einer Datenbank 3 Tabellen. Eine ist sozusagen die "Haupttabelle" und die beiden anderen sind eigentlich deshalb da weil die Daten aus einer veralteten Datenbank nicht anders zu exportieren sind. Nun soll die "Haupttabelle" jeweils mit den Informationen der beiden anderen einmalig abgleichen. Dieser Vorgang dauert sehr lange (ca. 5min.). Kann es sein, daß das ganze von mir aufgrund meiner Unwissenheit blöd gemacht ist und man das um einiges beschleunigen könnte?

Code:
-----------------------------------------------------------
<?
 $server = "localhost";
 $user   = "xxxxxxxxx";
 $pass   = "xxxxxxxxx";
 $dbase  = "xxxxxxxxx";

$conn = @mysql_connect($server, $user, $pass);

if($conn) {
    mysql_select_db($dbase, $conn);
 } else {
    die("Fehler, Verbindung konnte nicht hergestellt werden!");
 }

$sql = " SELECT  F1, F2, F5, F6, F9, F11, F21, F12 FROM Tabelle1";

$res = mysql_query($sql);
 $anz = mysql_num_rows($res);

$sql2 = $sql." ORDER BY F1 ASC";
 $res2 = mysql_query($sql2);
 $anz2 = mysql_num_rows($res2);

while ($row = mysql_fetch_array($res2, MYSQL_ASSOC)) {

$ht = mysql_fetch_array(mysql_query('SELECT F1, F2 FROM ht WHERE F1 = '.$row[F5].''));
 $ut = mysql_fetch_array(mysql_query('SELECT F1, F2 FROM ut WHERE F1 = '.$row[F6].''));
 echo $ht[F2]." ".$row[F2]." ".$ut[F2]."<br>";
 mysql_query('UPDATE Tabelle1 SET F28 = "'.$ht[F2].'" WHERE CONCAT( F1 ) = '.$row[F1].'');
 mysql_query('UPDATE Tabelle1 SET F29 = "'.$ut[F2].'" WHERE CONCAT( F1 ) = '.$row[F1].'');
 }
?>
-----------------------------------------------------------

Ich wäre Euch wirklich mehr als dankbar falls Ihr mir helfen könntet.

  1. Moin Hannes,

    Hallo! Hätte da mal eine Frage.

    Welche Du bereits hier gestellt hast:

    https://forum.selfhtml.org/?t=131683&m=851868

    regds
    Mike©

    --
    Freunde kommen und gehen. Feinde sammeln sich an.
  2. Hallo,

    du machst dieses:
      $res = mysql_query($sql);
      $anz = mysql_num_rows($res);

    wertest aber weder $res noch $anz aus. Das kostet natürlich Zeit. Falls du die Gesamtzahl der Sätze brauchst, wäre SELECT count(*) wohl angebrachter.

    Kalle

  3. Hallo,

    Dieser Vorgang dauert sehr lange (ca. 5min.). Kann es sein, daß das ganze von mir aufgrund meiner Unwissenheit blöd gemacht ist und man das um einiges beschleunigen könnte?

    Generell gilt: Jeder Datenbankaufruf ist teuer (im Sinne von dauert lange). Du solltest deshalb Table-Joins verwenden, wenn Du daten aus verschiedenen Tabellen benötigst:

    $sql = "SELECT
            tabelle1.F1,
            tabelle1.F2 AS T1_F2,
            ht.F1,
            ht.F2 AS ht_F2,
            ut.F1,
            ut.F2 AS ut_F2,
            tabelle1.F5,
            tabelle1.F6,
            tabelle1.F9,
            tabelle1.F11,
            tabelle1.F21,
            tabelle1.F12
            FROM tabelle1,ht,ut
            WHERE
            tabelle1.F5 = ht.F1 AND
            tabelle1.F6 = ut.F1";

    while ($row = mysql_fetch_array($res2, MYSQL_ASSOC)) {
        echo $row[ht_F2]." ".$row[T1_F2]." ".$row[ut_F2]."<br>";
    }

    Update müsste auch über mehrere Tabellen gehen und sich mit SELECTs verschachteln lassen, hierzu solltest Du mal die Dokumentation Deiner Datenbank zu rate ziehen, das habe ich gerade nicht im Kopf.

    Grüße,
    Jörg

    1. Hallo Jörg!

      $sql = "SELECT
              tabelle1.F1,
              tabelle1.F2 AS T1_F2,
              ht.F1,
              ht.F2 AS ht_F2,
              ut.F1,
              ut.F2 AS ut_F2,
              tabelle1.F5,
              tabelle1.F6,
              tabelle1.F9,
              tabelle1.F11,
              tabelle1.F21,
              tabelle1.F12
              FROM tabelle1,ht,ut
              WHERE
              tabelle1.F5 = ht.F1 AND
              tabelle1.F6 = ut.F1";

      while ($row = mysql_fetch_array($res2, MYSQL_ASSOC)) {
          echo $row[ht_F2]." ".$row[T1_F2]." ".$row[ut_F2]."<br>";
      }

      Da erhalte ich folgende Fehlermeldung (ich bin leider nicht besonders fit in PHP & mySQL):

      Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /xxx/htdocs/xxxxxxxxxx/xxx/test.php on line 37

      @ Mike©:
      Tut mir leid, kommt nicht wieder vor.

    2. Hallo Jörg,

      Generell gilt: Jeder Datenbankaufruf ist teuer (im Sinne von dauert lange). Du solltest deshalb Table-Joins verwenden, wenn Du daten aus verschiedenen Tabellen benötigst:

      $sql = "SELECT
              tabelle1.F1

      [...]

      FROM tabelle1,ht,ut
              WHERE
              tabelle1.F5 = ht.F1 AND
              tabelle1.F6 = ut.F1";

      generell gilt, das Du Dich gern einmal mit der expliziten JOIN-Syntax auseinandersetzen könntest, siehe Einführung JOINS. Ich finde die Schreibweise nicht nur schöner, sondern auch sauberer strukturiert. Uralte DBMS, die diese Schreibweise noch nicht unterstützen, dürften inzwischen extrem selten geworden sein - und wenn man sich mit sowas noch herumplagen muss, wie z.B. dem MS SQL-Server 4.21 von 1993, dann ist man sowieso auf das entsprechende Handbuch angewiesen.

      Ein Tabellen-Alias hätte sich hier angeboten, z.B. um Schreibarbeit zu sparen.

      Update müsste auch über mehrere Tabellen gehen

      Ja, das geht.

      und sich mit SELECTs verschachteln lassen,

      das geht auch (mit Einschränkungen), ist hier aber vermutlich nicht erforderlich.

      Dass folgende Kombination:

      $sql = "SELECT

      [...]

      while ($row = mysql_fetch_array($res2, MYSQL_ASSOC)) {
          echo $row[ht_F2]." ".$row[T1_F2]." ".$row[ut_F2]."<br>";
      }

      eine Fehlermeldung hervorruft, ist sonnenklar - und hängt an der ungeschickten Wahl der Variablennamen, die Du hier netterweise durcheinandergewürfelt hast, damit der OP sein Gehirn auch ein klein wenig anstrengen darf.

      Ich war so unfair, und habe den ganzen PHP-Kram gleich weggelassen ...

      Freundliche Grüße

      Vinzenz

      1. Moin,

        generell gilt, das Du Dich gern einmal mit der expliziten JOIN-Syntax auseinandersetzen könntest, siehe Einführung JOINS.

        Ah, danke für den Tip. Die explizite Syntax war mir wohl ein Begriff.
        Im SQL-Kurs im 6. Semester haben sie uns noch davor gewarnt, die zu
        benutzen (weils eben nicht jedes DBMS unterstützt), aber das war wohl nicht mehr so ganz taufrisches Wissen *g*

        eine Fehlermeldung hervorruft, ist sonnenklar - und hängt an der ungeschickten Wahl der Variablennamen, die Du hier netterweise durcheinandergewürfelt hast, damit der OP sein Gehirn auch ein klein wenig anstrengen darf.

        Hoppale, sorry - ich war in Eile :)

  4. Hallo

    Hallo! Hätte da mal eine Frage.

    ich habe zwar ein paar Antwortvorschläge, aber mehr als eine Frage an Dich.
    Zuerst: Welche MySQL-Version verwendest Du?

    Bei MySQL ist es immer ratsam, die verwendete Version mit anzugeben, da sich die Fähigkeiten von Version zu version sehr stark unterscheiden können. Eine neuere Version kann z.B. einen ganz anderen Lösungsvorschlag bedeuten.

    Ich habe in einer Datenbank 3 Tabellen. Eine ist sozusagen die "Haupttabelle" und die beiden anderen sind eigentlich deshalb da weil die Daten aus einer veralteten Datenbank nicht anders zu exportieren sind.

    Wie werden diese Daten exportiert?

    Nun soll die "Haupttabelle" jeweils mit den Informationen der beiden anderen einmalig abgleichen.

    Ist dies überhaupt nötig? Je nach verwendeter MySQL-Version könntest Du eventuell auf diesen Vorgang verzichten - und das ohne an Funktionalität zu verlieren.

    Dieser Vorgang dauert sehr lange (ca. 5min.). Kann es sein, daß das ganze von mir aufgrund meiner Unwissenheit blöd gemacht ist

    Wahrscheinlich.

    und man das um einiges beschleunigen könnte?

    Wahrscheinlich kann man das enorm vereinfachen und damit beschleunigen.

    Code:

    Trauriger Code, kein einziger Kommentar, nur ein rudimentärer Ansatz einer Fehlerbehandlung. Ich muss also raten, welche Voraussetzungen gelten, ich muss also raten, was Du vorhast. Ich versuche, so gezielt wie möglich zu raten.

    $sql = " SELECT  F1, F2, F5, F6, F9, F11, F21, F12 FROM Tabelle1";

    $res = mysql_query($sql);
    $anz = mysql_num_rows($res);

    Wie Kalle bereits angemerkt hat, verwendest Du diese Daten überhaupt nicht. Sie können an dieser Stelle weggelassen werden, damit wird Dein Skript bereits etwas schneller

    $sql2 = $sql." ORDER BY F1 ASC";
    $res2 = mysql_query($sql2);
    $anz2 = mysql_num_rows($res2);

    Wie ich bereits an anderer Stelle anmerkte, sind das schlecht gewählte Variablennamen. Hier gehe ich noch einen Schritt weiter. Deine Feldnamen sind eine einzige Katastrophe. Solche Namen gehören in Coderichtlinien verboten :-)

    Weiterhin fragst Du die Spalten F9, F11, F12 und F21 ab, ohne diese Daten je zu nutzen. Grundsätzlich solltest Du keine Daten abrufen, die Du ungenutzt wegwirfst. Es beschleunigt das ganze auch ein wenig.

    Nun zu Deiner while-Schleife. Ich versuche herauszufinden, was Du vorhast.

    while ($row = mysql_fetch_array($res2, MYSQL_ASSOC)) {

    $ht = mysql_fetch_array(mysql_query('SELECT F1, F2 FROM ht WHERE F1 = '.$row[F5].''));

    Zu jeder Zeile der Tabelle "Tabelle1" (noch ein ungünstig gewählter Name) suchst Du _genau einen_ einen passenden Eintrag in der Tabelle ht (nicht viel besser). Du gehst davon aus, dass ein solcher Eintrag existiert, Du interessierst Dich nur für den ersten Eintrag. Ich folgere daraus, dass es genau einen passenden Eintrag dazu gibt. Dabei korrespondiert der Wert in der Spalte F1 der Tabelle ht mit dem Wert der Spalte F5 in Tabelle1.

    $ut = mysql_fetch_array(mysql_query('SELECT F1, F2 FROM ut WHERE F1 = '.$row[F6].''));

    Hier gehst Du analog vor: ut.F1 entspricht Tabelle1.F6

    Wie Jörg bereits angemerkt hat, solltest Du dazu mit Joins arbeiten und nicht mit einer While-Schleife. Ich liefere Dir dazu Links zu den JOIN-Artikeln:

    Einführung JOINS
    Fortgeschrittenene Joins

    echo $ht[F2]." ".$row[F2]." ".$ut[F2]."<br>";
    mysql_query('UPDATE Tabelle1 SET F28 = "'.$ht[F2].'" WHERE CONCAT( F1 ) = '.$row[F1].'');

    Deine WHERE-Klausel kommt mir reichlich sinnfrei vor: Welchen Vorzug hat sie gegenüber einem einfachen WHERE F1 = '[code lang=php] . $row['F1'] . '[/code]. Einen PHP-Fehler habe ich dabei schon korrigiert :-)

    mysql_query('UPDATE Tabelle1 SET F29 = "'.$ut[F2].'" WHERE CONCAT( F1 ) = '.$row[F1].'');
    }

    Grundsätzlich ist der ganze PHP-Kram völlig überflüssig, wenn meine Annahmen stimmen. Dann reicht Dir folgendes einfache SQL-Statement, siehe auch MySQL-Handbuch, UPDATE-Syntax:

    UPDATE Tabelle1 t               -- Aliasname, um Schreibarbeit zu sparen :-)  
    INNER JOIN ht ON t.F5 = ht.F1   -- Qualifizierte Spaltennamen, wenn mehrfach  
    INNER JOIN ut ON t.F6 = ut.F1  
    SET  
        t.F28 = ht.F2,              -- Update von F28 mit Wert aus Tabelle ht  
        t.F29 = ut.F2               -- Update von F29 aus Wert aus Tabelle ut  
    
    

    Schicke dieses Statement mit dem MySQL-Client Deiner Wahl, von mir aus auch PHP an den entsprechenden MySQL-Server mit vorheriger Auswahl der gewünschten Datenbank und Du solltest Dein Ziel erreichen.

    Als Alternative käme, MySQL 5.x vorausgesetzt, der Einsatz von Views in Frage, so dass das Aktualisieren der Tabelle entfallen könnte.

    Bitte nimm den Hinweis von Mike ernst. Ich habe überlegt, wo ich Dir antworte und mich für diesen Thread hier entschieden, weil von hier aus auch Dein Ausgangsthread erreichbar ist und andererseits Dir schon zwei Vorschläge gemacht wurden. Grundsätzlich zielte der Beitrag von H.P. Ortner in die richtige Richtung, es fehlten die JOINS und die Idee, alles in einem Aufwasch zu erledigen.

    Wenn mein Vorschlag Dein Problem nicht lösen sollte, so liegt dies an Deinem Ausgangsposting, das zu viele Fragen offenläßt und die Situation nicht genau genug beschreibt. Bei solchen Fragen wie Deiner ist es immer eine gute Idee, ein paar Beispieldatensätze mit anzugeben und aufzuzeigen, wie das Ergebnis aussehen soll - und warum.

    Freundliche Grüße

    Vinzenz