[SQL allgemein] Abfrageproblem

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

  • Wurzel
    antwortet
    oh happy, das wird ne längere geschichte

    also erstmal: ich krieg jetzt in der while-schleife die erwartete ausgabe
    (das warum klären wir später)

    die funktion liefert aber nach wie vor nix => ist also leer
    PHP-Code:
    $result mysql_query($sql,$conn) or die(mysql_error());
    mysql_num_rows($result);
    $rows mysql_fetch_array($result);


    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(':',$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); 
    definier ich $rows/$result falsch?

    PS: dir ist schon klar, dass ich bisher noch nicht so genau weiss, was wir hier tun

    Einen Kommentar schreiben:


  • mrhappiness
    antwortet
    in deiner tabelle menu_has_menu sind zu wenig einträge (und verkehrt rum)

    so sollte es gehen
    Code:
    INSERT INTO menu_has_menu 
    VALUES 
      (0, 37), 
      (0, 97), 
      (0, 120), 
      (0, 129), 
      (0, 130), 
      (0, 131),
      (0, 132),
      (0, 135),
      (120, 129),
      (120, 130),
      (120, 131),
      (120, 132),
      (120, 135),
      (131, 132),
      (131, 135)
    du musst die komplette hierarchie für jeden punkt speichern

    Einen Kommentar schreiben:


  • Wurzel
    antwortet
    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.

    Einen Kommentar schreiben:


  • mrhappiness
    antwortet
    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?

    Einen Kommentar schreiben:


  • mrhappiness
    antwortet


    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

    Einen Kommentar schreiben:


  • TBT
    antwortet
    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 

    Einen Kommentar schreiben:


  • mrhappiness
    antwortet
    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

    Einen Kommentar schreiben:


  • TBT
    antwortet
    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()) 

    Einen Kommentar schreiben:


  • mrhappiness
    antwortet
    *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?

    Einen Kommentar schreiben:


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

    Einen Kommentar schreiben:


  • mrhappiness
    antwortet
    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

    Einen Kommentar schreiben:


  • MoRtAlAn
    antwortet
    die erweiterung auf mehrere Bäume ist recht unkompliziert

    man hilft, wo man kann

    Einen Kommentar schreiben:


  • mrhappiness
    antwortet
    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

    Einen Kommentar schreiben:


  • MoRtAlAn
    antwortet
    mh... irgendwie fehlt eine spalte...

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

    Einen Kommentar schreiben:


  • mrhappiness
    antwortet
    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.

    Einen Kommentar schreiben:

Lädt...
X