[SQL allgemein] Abfrageproblem

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

  • [SQL allgemein] Abfrageproblem

    schaut euch bitte hier mal die folgende abfrage an
    Code:
    SELECT
      e1.menu_name e1_name, 
      e2.menu_name e2_name,
      e3.menu_name e3_name
    FROM
      menu e1
      LEFT JOIN menu e2 ON e1.menu_id=e2.parent_id
        LEFT JOIN menu e3 ON e2.menu_id=e3.parent_id
    WHERE e1.parent_id=0
    kann ich die abfrage auch so machen, dass ich in der selben spalte erst die übergeordnete kategorie und dann die untergeordneten habe?
    Ich denke, also bin ich. - Einige sind trotzdem...

  • #2
    kannst du die reihenfolge anhand des ausgabebeispiels mal kurz angeben, wie du es haben willst ?

    gruss

    Kommentar


    • #3
      hätt ich's gern:
      Code:
      parent_id | menu_id | menu_name
              0 |       1 | hauptkategorie 1
              1 |       3 | unterkategorie 1.1
              1 |       4 | unterkategorie 1.2
              4 |       7 | unterkategorie 1.2.1
              1 |       5 | unterkategorie 1.3
              0 |       2 | hauptkategorie 2
              2 |       6 | unterkategorie 2.1
              0 |       8 | hauptkategorie 3
      Zuletzt geändert von mrhappiness; 08.08.2003, 11:01.
      Ich denke, also bin ich. - Einige sind trotzdem...

      Kommentar


      • #4
        mh... irgendwie fehlt eine spalte...

        schau dir mal das nested sets model an:
        www.develnet.org -> tutorials

        Kommentar


        • #5
          sieht fein aus, gleich mal übernommen

          hatt zwar kleine problemchen mit mehreren bäumen in der tabelle, aber jetzt dem geht

          habe er tausend dank
          Ich denke, also bin ich. - Einige sind trotzdem...

          Kommentar


          • #6
            die erweiterung auf mehrere Bäume ist recht unkompliziert

            man hilft, wo man kann

            Kommentar


            • #7
              deswegen ja "kleine problemchen" ( = verschrieben bei den sql-statements)

              aber ein prob hab ich noch

              du kannst dirja, wenn du zeit und lust hast, mal hier die tabelle node anschauen

              da gibts die punkte:
              1
              1.1
              1.1.1
              1.2
              1.2.1
              1.2.1.1
              1.2.1.2
              1.3
              1.3.1
              2
              2.1
              2.2
              diese punkte krieg ich so mit einer einzigen abfrage
              Code:
              SELECT
                node1.payload, , COUNT( * ) level
              FROM node node1, node node2
              WHERE 
                node1.root_id = node2.root_id 
                  AND node1.lft BETWEEN node2.lft AND node2.rgt
              GROUP BY 
                node1.lft, node1.root_id
              ORDER BY 
                node1.root_id, node1.lft, node1.rgt
              aber wie müsste eine abfrage aussehen, die mir z.b.
              1
              1.1
              1.2
              1.2.1
              1.3
              2
              liefert?
              sinnund zweck: benutzer klickt auf 1 und menü 1 klappt auf, er klickt auf 1.2 und menü 1.2 klappt auf; geht das in einer abfrage (beliebig tief)?

              ich würde dann bei meiner navigation gerne nur die node_id (primärschlüssel) von 1.2 übergeben und das soll rauskommen
              Ich denke, also bin ich. - Einige sind trotzdem...

              Kommentar


              • #8
                schau dir mal den hier an:
                http://www.php-resource.de/forum/sho...threadid=23912

                Kommentar


                • #9
                  *grmpf*

                  irgendwie will das nich
                  select:
                  Code:
                  SELECT 
                    node1.payload, node1.root_id, node1.node_id, node1.lft, node1.rgt, 
                    COUNT( * ) level 
                  FROM node node1
                    INNER JOIN node node2 USING ( root_id )
                  WHERE node1.lft BETWEEN node2.lft AND node2.rgt
                  GROUP BY 
                    node1.lft, node1.root_id
                  ORDER BY
                    node1.root_id, node1.lft, node1.rgt
                  ausgabe:
                  Code:
                  payload | root_id | node_id | lft | rgt | level
                  1         1          1         1    18    1
                  1.1       1          2         2     5    2
                  1.1.1     1          6         3     4    3
                  1.2       1          3         6    13    2
                  1.2.1     1          5         7    12    3
                  1.2.1.1   1         11         8     9    4
                  1.2.1.2   1         12        10    11    4
                  1.3       1          4        14     7    2
                  1.3.1     1         10        15    16    3
                  2         2          7         1     6    1
                  2.1       2          8         2     3    2
                  2.2       2          9         4     5    2
                  aber ich krieg irgendwie kein select hin, das mir in einem rutsch das hier liefert:
                  Code:
                  payload | root_id | node_id | lft | rgt | level
                  1         1          1         1    18    1
                  1.1       1          2         2     5    2
                  1.2       1          3         6    13    2
                  1.2.1     1          5         7    12    3
                  1.2.1.1   1         11         8     9    4
                  1.2.1.2   1         12        10    11    4
                  1.3       1          4        14     7    2
                  2         2          7         1     6    1
                  und so sollte es ja aussehen, wenn sich mein besucher durch meine menüstruktur klickt

                  aber anscheinend bin ich zu blöd um das hier als sql-select zu formulieren:Klapp alle Äste soweit wie nötig auf um die unterpunkte vom eintrag mit node_id 5 (1.2.1) anzuzeigen)

                  ideas?
                  Ich denke, also bin ich. - Einige sind trotzdem...

                  Kommentar


                  • #10
                    und wieso nicht mit zwei Tabellen, welche
                    genau alle deine Wünsche erfüllen ?

                    Code:
                    CREATE TABLE menu (
                      menu_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
                      parent_id INTEGER UNSIGNED NOT NULL,
                      name VARCHAR(255) NOT NULL,
                      sort INTEGER UNSIGNED NOT NULL,
                      PRIMARY KEY(menu_id)
                    );
                    
                    CREATE TABLE menu_has_menu (
                      menu_id INTEGER UNSIGNED NOT NULL,
                      child_id INTEGER UNSIGNED NOT NULL,
                      PRIMARY KEY(menu_id, child_id)
                    );
                    und Menu bauen mit
                    PHP-Code:
                    $sql='SELECT m2.menu_id, m2.sort, m2.parent_id, m2.name
                        FROM  menu m 
                        LEFT JOIN menu_has_menu mm 
                            ON  ( m.menu_id = mm.child_id ) 
                        LEFT JOIN menu m2 
                            ON ( mm.menu_id = m2.parent_id )
                        LEFT JOIN menu_has_menu mm2
                            ON ( m2.menu_id = mm2.child_id )
                        WHERE m.menu_id = '
                    .$menu.' or m.parent_id = '.$menu.
                        GROUP BY m2.menu_id, m2.parent_id, m2.sort 
                        ORDER BY m2.parent_id,  m2.sort'
                    ;
                        
                    function &
                    build_menu(&$result,&$rows,$parent=0,$level=0){
                        
                    $output '';
                        for(
                    $i=0;$i<$rows;++$i){
                            if(
                    $result[$i]['parent_id']==$parent){
                                
                    $output .= str_repeat('&raquo; &raquo; ',$level).' <a href="index.php?menu='.$result[$i]['menu_id'].'">'.$result[$i]['name'].'</a><br>';
                                
                    $output .= build_menu($result,$rows,$result[$i]['menu_id'],$level+1);
                            }
                        }
                        return 
                    $output;
                    }

                    $menu_var build_menu($result,$rows);

                    // PS: $result ist ein Array(mysql_fetch_array()) 
                    TBT

                    Die zwei wichtigsten Regeln für eine berufliche Karriere:
                    1. Verrate niemals alles was du weißt!


                    PHP 2 AllPatrizier II Browsergame

                    Kommentar


                    • #11
                      weil, ähm, ja, also...

                      hab mich jetzt grad mit nested sets angefreundet und damit sollte es doch auch gehen oder?

                      ich probier noch etwas rum und hoffe drauf, dass jemand weiß wie's bei nested sets geht und wenn ich's nich hinkrieg werd ich wohl deinen vorschlag nehmen

                      seh ich das richtig, das in $result alles drinsteht was mir das select liefert, also alle datensätze und in $rows steht einfach nur die anzahl der datensätze?

                      wenn ich 1.2 hab und will 1.2.1 anlegen, mach ich dann
                      Code:
                      INSERT INTO menu
                       SET
                          parent_id=<id von 1.2>,
                          name='1.2.2',
                          sort=1
                      
                      INSERT INTO menu_has_menu
                        SET
                          menu_id=<id von 1.2.1>,
                          parent_id=<id von 1.2>
                      ?


                      auf jeden fall vielen dank
                      Ich denke, also bin ich. - Einige sind trotzdem...

                      Kommentar


                      • #12
                        nicht ganz, in "menu_has_menu" stehen alle übergeordneten drin, incl. der 0
                        also so:

                        PHP-Code:
                        0 1 1. )
                        0 2 2. )
                        0 3 1.1 )
                        1 3 1.1 // über 1.1 sind 1 und 0 !
                        0 4 2.1 )
                        2 4 2.1 // über 2.1 sind 2 und 0 !
                        0 5 1.1.1 )
                        1 5 1.1.1 )
                        3 5 1.1.1 // über 1.1.1 sind 1, 1.1 und 0 
                        TBT

                        Die zwei wichtigsten Regeln für eine berufliche Karriere:
                        1. Verrate niemals alles was du weißt!


                        PHP 2 AllPatrizier II Browsergame

                        Kommentar


                        • #13


                          ich krieg mittlerweile die direkten nachfolger mit einem select und die direkten vorgänger mit nem anderen select, also einmal:
                          1.2.1.1
                          1.2.1.2
                          Code:
                          SELECT 
                            n1.payload
                          FROM node n1
                            INNER JOIN node n2 USING (root_id)
                          WHERE 
                            n1.lft BETWEEN n2.lft AND n2.rgt 
                            AND
                            (n2.payload != n1.payload OR n1.lft = 1)
                            AND n2.node_id = 5
                          und:
                          1
                          1.2
                          1.2.1
                          Code:
                          SELECT n1.payload
                          FROM node n1
                            INNER JOIN node n2 USING(root_id)
                          WHERE 
                            n2.lft BETWEEN n1.lft AND n1.rgt 
                            AND 
                            n2.rgt BETWEEN n1.lft AND n1.rgt 
                            AND 
                            n2.node_id = 5
                          fehlen mir noch
                          1.1
                          1.3
                          2

                          ich könnte mir jetzt für jeden vorgänger die brüder raussuchen, aber dann hab ich tausende von selects

                          bin fast geneigt TBTs variante zu nehmen, es sei denn es fällt noch jemandem ganz spontan was ein...

                          mrhappiness, die hoffnung und das vertrauen in euch nicht aufgibt
                          Ich denke, also bin ich. - Einige sind trotzdem...

                          Kommentar


                          • #14
                            hab TBTs variante genommen

                            aber eine frage noch, ich hab meine datensätze in der spalte sort durchgehen nummeriert, also nicht für jede neue eben bei 1 begonnen und nur sort als sortierkriterium genommen

                            wenn ich nach parent_id und dann nach sort sortieren lasse bekomme ich nämlich:
                            1
                            2
                            1.1
                            1.2
                            1.3
                            1.2.1
                            und das is eher plöt

                            oder hab ich da was flhacs gemacht
                            EDIT:
                            hab gradgesehen, dass ich deine funktion ja noch gar nich drin hatte, hab's mir nur in phpmyadmin angeschaut und da kann das ja so nich gehen

                            aber ich bild mir ein, dass es (nur nach sort sortieren) bei der abfrage evtl. performanter is, beim pflegen allerdings aufwendiger oder?

                            Ich denke, also bin ich. - Einige sind trotzdem...

                            Kommentar


                            • #15
                              hallo zusammen,

                              hab mich hier mal durchgewurschtelt ... krieg aber zum verrecken keine vernünftige ausgabe hin.

                              - in der (testhalber eingefügten) while-schleife erhalte ich ein ergebnis, das falsch ist.
                              - die funktion von tbt liefert mir null, nada, gar nichts zurück.

                              phpMyAdmin sagt nach der sql-abfrage "zeige 0-8 datensätze von 8" spuckt
                              aber nur 2 aus (die ich garnicht will) plus eine zeile mit "null|null|null|null" ?!

                              kann mich mal jemand aufklären?

                              PHP-Code:
                              <?
                              /*
                              #
                              # Tabellenstruktur für Tabelle `n_menu`
                              #

                              CREATE TABLE n_menu (
                                menu_id int(10) unsigned NOT NULL auto_increment,
                                parent_id int(10) unsigned NOT NULL default '0',
                                name varchar(255) NOT NULL default '',
                                sort int(10) unsigned NOT NULL default '0',
                                PRIMARY KEY  (menu_id)
                              ) TYPE=MyISAM;

                              #
                              # Daten für Tabelle `n_menu`
                              #

                              INSERT INTO n_menu VALUES (37, 0, 'home', 1);
                              INSERT INTO n_menu VALUES (97, 0, '2.punkt', 2);
                              INSERT INTO n_menu VALUES (120, 0, '3.punkt', 3);
                              INSERT INTO n_menu VALUES (129, 120, '1.sub', 1);
                              INSERT INTO n_menu VALUES (130, 120, '2.sub', 2);
                              INSERT INTO n_menu VALUES (131, 120, '3.sub', 3);
                              INSERT INTO n_menu VALUES (132, 131, '1.subsub', 1);
                              INSERT INTO n_menu VALUES (135, 131, '2.subsub', 2);


                              CREATE TABLE menu_has_menu (
                                menu_id int(10) unsigned NOT NULL default '0',
                                child_id int(10) unsigned NOT NULL default '0',
                                PRIMARY KEY  (menu_id,child_id)
                              ) TYPE=MyISAM;

                              #
                              # Daten für Tabelle `menu_has_menu`
                              #

                              INSERT INTO menu_has_menu VALUES (37, 0);
                              INSERT INTO menu_has_menu VALUES (97, 0);
                              INSERT INTO menu_has_menu VALUES (120, 0);
                              INSERT INTO menu_has_menu VALUES (129, 120);
                              INSERT INTO menu_has_menu VALUES (130, 120);
                              INSERT INTO menu_has_menu VALUES (131, 120);
                              INSERT INTO menu_has_menu VALUES (132, 131);
                              INSERT INTO menu_has_menu VALUES (135, 131);
                              # --------------------------------------------------------
                              */


                              $menu = 120;
                              $sql='SELECT m2.menu_id, m2.sort, m2.parent_id, m2.name
                                  FROM  n_menu m
                                  LEFT JOIN menu_has_menu mm 
                                      ON  ( m.menu_id = mm.child_id ) 
                                  LEFT JOIN n_menu m2
                                      ON ( mm.menu_id = m2.parent_id )
                                  LEFT JOIN menu_has_menu mm2
                                      ON ( m2.menu_id = mm2.child_id )
                                  WHERE m.menu_id = '.$menu.' or m.parent_id = '.$menu.' 
                                  GROUP BY m2.menu_id, m2.parent_id, m2.sort 
                                  ORDER BY m2.parent_id,  m2.sort';


                              $result = mysql_query($sql,$conn) or die(mysql_error());
                              mysql_num_rows($result);
                              $rows = mysql_fetch_array($result);

                              // hier gibbet ne ausgabe, aber die ist falsch
                              while($rows = mysql_fetch_array($result))
                              {
                                  echo $rows['name']."<br />";
                              }

                              function &build_menu(&$result,&$rows,$parent=0,$level=0){
                                  $output = '';
                                  for($i=0;$i<$rows;++$i){
                                      if($result[$i]['parent_id']==$parent){
                                          $output .= str_repeat('&raquo; &raquo; ',$level).' <a href="index.php?menu='.$result[$i]['menu_id'].'">'.$result[$i]['name'].'</a><br>';
                                          $output .= build_menu($result,$rows,$result[$i]['menu_id'],$level+1);
                                      }
                                  }
                                  return $output;
                              }
                              echo $menu_var = build_menu($result,$rows); // ausgabe hier ""
                              ?>
                              erwarten würde ich eine ausgabe wie diese:
                              -home
                              -2.punkt
                              -3.punkt
                              >>1.sub
                              >>2.sub
                              >>3.sub
                              ... also alle unterpunkte direkt unter menu_id 120.
                              Kissolino.com

                              Kommentar

                              Lädt...
                              X