Self Join, hilfe beim Ansatz.

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Self Join, hilfe beim Ansatz.

    Ich habe eine MySQL Tabelle namens navigation, die sieht wie folgt aus:


    Das Ziel ist es, dass die Ausgabe so aussieht:
    News
    - News Test 1
    - News Test 2
    - News Test 3
    Artikel
    - Artikel 1
    - Artikel 2
    - Artikel 3

    Prinzip dahinter ist einfach. Es gibt eine Kategorie (category = 1) und diese haben jeweils Unter-Kategorien welche durch die parentID zugewiesen sind.

    Bis jetzt habe ich das immer so gelöst:
    PHP-Code:
    $result mysql_query('SELECT * FROM navigation WHERE category = "1"') or die (mysql_error());
    while(
    $row mysql_fetch_array($result))
    {
    echo 
    $row['name']);
            
        
    $result2 mysql_query('SELECT * FROM navigation WHERE category = "0" AND parentID = "'.$row[id].'"') or die (mysql_error());
        while(
    $row2 mysql_fetch_array($result2))
        {
            echo 
    $row2[name]);
        }

    Nun wurde mir aber gesagt dass dies sehr schlecht ist für den MySQL Server, da man generell keine Querys in einer while schleife haben sollte, was ich auch einsehe.
    Mir wurde gesagt ich soll dies am besten mit einem JOIN in der Query direkt lösen.

    Kann mir jemand hier auf die sprünge helfen, wie ich das genau mit einem JOIN hinbekomme, so dass die Ausgabe wieder die selbe ist?
    Eventuell müsste die Tabelle um ein Feld erweitert werden (ordnungsnummer).

  • #2
    Re: Self Join, hilfe beim Ansatz.

    Versuch doch erstmal selbst, die JOIN-Query zu formulieren und poste sie, wenn du nicht weiterkommst.
    Die Tabelle muss übrigens nicht erweitert werden. Dein JOIN-Kriterium ist n2.parentID = n1.id.

    Nochwas: Alle Spalten außer name sollten numerischen Typs sein!
    Zuletzt geändert von onemorenerd; 01.07.2008, 14:48.

    Kommentar


    • #3
      JOIN:

      HOLE alle datensäte (und die zugehörigen parentcats)
      DIE parent_id != 0
      HABEN.


      Und das Ergebnis einfach mit nem Gruppenwechsel so formatieren, wie du es gerne dar.

      ------------------

      Alternativ, bei Strukturen beliebiger Tiefe:

      Einfach alle relevanten Datensätze aus der DB holen, dann in ein Array stopfen:

      $navi[ID] => array (name => NAME, children => array());

      Wenn eine Parent-ID angegeben wurde, wird das array in das entsprechende "children"->Array gepackt:

      $navi[ID] => array (name => NAME, children => array($navi[ID] => array (name => NAME, children => array())));

      Das ganze lässt sich beliebig verschachteln.
      Die Ausgabe erfolgt dann rekursiv.

      Hier sollte man dann aber ggf. über eine andere Datenstruktur nachdenken.
      Zuletzt geändert von TobiaZ; 01.07.2008, 14:52.

      Kommentar


      • #4
        Original geschrieben von TobiaZ
        Wozu nen Join?

        Einfach alle relevanten Datensätze aus der DB holen ...
        Es sind genau die Datensätze relevant, die ein JOIN liefern würde.

        Wenn der JOIN bei ihm immer alle Datensätze liefert, kann er deinem Vorschlag folgen. Über JOINs hat er dann aber immernoch nichts gelernt.

        Kommentar


        • #5
          Hatte mich grade vom Monitor abgewandt, da dämmerte mir, was er vorhatte.

          Kommentar


          • #6
            Danke euch beiden.

            Was ich bisher hatte:

            PHP-Code:
            $result mysql_query('
            SELECT 
                 n1.ID AS "n1.ID"
                ,n1.name AS "n1.name"
                ,n1.category AS "n1.category"
                ,n1.parentID AS "n1.parentID"
                ,n2.ID AS "n2.ID"
                ,n2.name AS "n2.name"
                ,n2.category AS "n2.category"
                ,n2.parentID AS "n2.parentID" 
            FROM navigation n1 
            LEFT JOIN navigation n2 ON n2.parentID=n1.ID'
            ) or die (mysql_error());
            while(
            $row mysql_fetch_array($result))
            {
                echo 
            ''.$row['n1.name'].'-'.$row['n2.name'].'';
                echo 
            '<hr />';

            Ausgabe:
            News - Test News 1
            News - Test News 2
            News - Test News 3
            Artikel - Artikel 1
            Artikel - Artikel 2
            Artikel - Artikel 3
            Test News 1 -
            Test News 2 -
            Artikel 1 -
            Test News 3 -
            Artikel 2 -
            Artikel 3 -

            Nur muss ich das ganze nun sinnvoll sortieren, und auch die Kategorie selber zum vorschein bringen.
            Edit: Ja die Nummerischen Felder sind als integer eingetragen.
            Zuletzt geändert von Londrag; 01.07.2008, 15:14.

            Kommentar


            • #7
              Ausgabe:
              News - Test News 1
              News - Test News 2
              News - Test News 3
              Artikel - Artikel 1
              Artikel - Artikel 2
              Artikel - Artikel 3
              Test News 1 -
              Test News 2 -
              Artikel 1 -
              Test News 3 -
              Artikel 2 -
              Artikel 3 -
              Da sind ja noch einige Datensätze zu viel!

              Nur muss ich das ganze nun sinnvoll sortieren
              Das sollte ja dank ORDER BY kein Problem sein.
              und auch die Kategorie selber zum vorschein bringen.
              Hierfür sprach ich den Gruppenwechsel an.

              Kommentar


              • #8
                Wenn du die Einschränkungen für category wie im Eingangsbeitrag einbaust, werden es weniger Datensätze. Du willst ja erreichen, dass beim Self Join die Tabelle einmal die Kategorien und einmal die Einträge liefert. Also muss eine Instanz (n1 oder n2) auf category = 1 eingeschränkt werden und die andere auf category = 0.

                Kommentar


                • #9
                  Nun siehts so aus:
                  PHP-Code:
                  $result mysql_query('
                  SELECT 
                       n1.ID AS "n1.ID"
                      ,n1.name AS "n1.name"
                      ,n1.category AS "n1.category"
                      ,n1.parentID AS "n1.parentID"
                      ,n2.ID AS "n2.ID"
                      ,n2.name AS "n2.name"
                      ,n2.category AS "n2.category"
                      ,n2.parentID AS "n2.parentID" 
                  FROM navigation n1 
                  LEFT JOIN navigation n2 ON n2.parentID=n1.ID WHERE n1.ID = n2.parentID ORDER BY n1.ID, n2.ID'
                  ) or die (mysql_error());

                  while(
                  $row mysql_fetch_array($result))
                  {
                      echo 
                  ''.$row['n2.name'].'<hr />';

                  Ergibt:
                  Test News 1
                  Test News 2
                  Test News 3
                  Artikel 1
                  Artikel 2
                  Artikel 3

                  Was eigentlich bis auf die fehlende Kategorie korrekt ist.
                  Okay, also Gruppenwechsel oder Instanz?
                  Das Gruppenwechsel FAQ macht im erstenblick sinn, doch die variable $old hat keinen Wert, versteh ich nicht ganz.

                  Was genau meinst du mit Instanz? Eine zweite SQL Query? Beispiel? Es tut mir leid das ich mich so doof anstelle, doch ursprünglich wollte ich nur meine kleine navigation für PDO umschreiben, was ich für 10 min arbeit gehalten habe, doch nun sitz ich schon 3 Tage daran

                  Kommentar


                  • #10
                    Das Gruppenwechsel FAQ macht im erstenblick sinn, doch die variable $old hat keinen Wert, versteh ich nicht ganz.
                    $old hat nur am anfang keinen Wert, der wird dann später zugewiesen:

                    PHP-Code:
                        if($old != $row->lastname)
                        {
                        
                            echo \
                    '<h1>\' . $row->lastname . \'<h1>\';
                            $old = $row->lastname;
                            
                        } 
                    Danke für den Hinweis. Endlich mal jemand, der auch versucht die Tipps zu verstehen, anstatt sie nur umzusetzen (kopieren).

                    Kommentar


                    • #11
                      Ich danke euch beiden vielmals. Nun funktioniert es endlich!

                      PHP-Code:
                      $result mysql_query('
                      SELECT 
                           n1.ID AS "n1.ID"
                          ,n1.name AS "n1.name"
                          ,n1.category AS "n1.category"
                          ,n1.parentID AS "n1.parentID"
                          ,n2.ID AS "n2.ID"
                          ,n2.name AS "n2.name"
                          ,n2.category AS "n2.category"
                          ,n2.parentID AS "n2.parentID" 
                      FROM 
                          navigation n1 
                      LEFT JOIN 
                          navigation n2 ON n2.parentID=n1.ID 
                      WHERE 
                          n1.ID = n2.parentID  
                      ORDER BY 
                          n1.ID, n2.ID'
                      ) or die (mysql_error());

                      $var '';
                      while(
                      $row mysql_fetch_array($result))
                      {

                          if(
                      $var != $row['n1.name']) {
                              echo 
                      '<b>'.$row['n1.name'].'</b><hr />';
                              
                      $var $row['n1.name'];
                          }
                          echo 
                      ''.$row['n2.name'].'<hr />';

                      Ergibt:
                      News
                      Test News 1
                      Test News 2
                      Test News 3
                      Artikel
                      Artikel 1
                      Artikel 2
                      Artikel 3

                      Jetzt noch hoffen das ich das mit PDO hinkriege

                      Kommentar

                      Lädt...
                      X