Nested set mit zugeordneten Datensätzen kombinieren

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

  • Nested set mit zugeordneten Datensätzen kombinieren

    Hallo,

    ich habe wieder ein Problem, bei dem ich nicht weiterkomme.

    Es gibt eine als Nested set ausgelegte Tabelle mit Warengruppen (Unterwarengruppen etc.), eine Tabelle mit Artikeln und eine Zwischentabelle für die Verknüpfung der Artikel mit den Warengruppen.

    Ist es nun möglich, mit einer Abfrage die Warengruppen inkl. der dazugehörigen Artikel als ihre "Kinder" auszugeben?

    Mein Problem besteht darin, dass bei der Abfrage der Warengruppen ja mit GROUP BY gearbeitet wird. Folglich wird einer jeweiligen Warengruppe nur ein Artikel zugeordnet, nicht alle. Lässt sich das anders lösen?

    Mir ist klar, dass ich einmal den Baum der Warengruppen und einmal die Artikelzuordnungen auslesen und anschließend ein gesamtes Array erstellen könnte. Mich interessiert aber, ob es auch nur mit SQL möglich ist. Ich finde leider keinen sinnvollen Ansatz.

    Struktur:

    tbl_wgruppen: id, lft, rgt, name
    tbl_artikel: id, name
    tbl_zuordnung: id, artikel_id, wgruppen_id

    Angenommen, der Baum sieht so aus:
    Code:
    hosen
     |- lila
     |- blau
     |- gelb
    blumen
     |- rosa
     |- orange
         |- groß
         |- klein
     |- rot
    und die Artikel so:

    blume1 (gehört blumen-rosa,blumen-orange-klein)
    blume2 (gehört blumen-rot,blumen-orange-groß)

    Dann müsste das Ergebnis so aussehen:
    Code:
    hosen
     |- lila
     |- blau
     |- gelb
    blumen
     |- rosa
         |- blume1
     |- orange
         |- groß
             |- blume2
         |- klein
             |- blume1
     |- rot
         |- blume2
    Dadurch, dass die Abfrage des Baumes nun (grob) so aussieht:
    Code:
    SELECT wg2.*, COUNT(*) AS lev, ...
      FROM tbl_wgruppen wg1,
           tbl_wgruppen AS wg2
        WHERE wg2.lft BETWEEN wg1.lft AND wg1.rgt
      GROUP BY wg2.lft
    ergibt sich eben das Problem, dass beim Einbeziehen der Artikel und Artikelzuordnungen in die Abfrage einer Warengruppe (höchstens) nur ein Artikel zugeordnet wird; eben durch die Gruppierung.

    Hat sich schon jemand mal mit so einer Problemstellung befasst und weiß Abhilfe? Wie gesagt, es ist kein wichtiges Problem, sondern reines Interesse.

  • #2
    Mit einer einfachen Schleife (einlesen, ausgeben) wird das nix.

    Am Join liegt´s nicht, die Bedingung ließe sich ja ändern.
    Das Problem ist vielmehr, dass zusätzlich zu den Artikeln einer Warengruppe die Gruppe selbst als Datensatz benötigt wird.

    Mit etwas Aufwand in der Schleife ist das aber problemlos möglich:

    PHP-Code:
    $sql "
    select g.id wgruppen_id, g.lft, g.rgt, g.name wgruppen_name,
      a.id artikel_id, a.name artikel_name
    from tbl_wgruppen g
      left join tbl_zuordnung z on z.wgruppen_id=g.id
      left join tbl_artikel a on a.id=z.artikel_id
    group by g.lft, a.id
    order by g.lft, a.id"
    ;
    $res mysql_query($sql)
      or die (
    nl2br(htmlentties($sql). "\n"mysql_error()));
    $root mysql_fetch_assoc($res);
    $lvl2rgt = array(-1=>$root['rgt']);
    $level $wgruppen_id $lastrgt 0;
    echo 
    '<pre>';
    while (
    $row mysql_fetch_assoc($res))
    {
      if (
    $wgruppen_id<>$row['wgruppen_id'])
      { 
    // Warengruppe hat gewechselt - Datensatz ausgeben
        // Wenn LFT des aktuellen Datensatzes > RGT des parent-level --> nach links
        
    if ($row['lft']>$lvl2rgt[$level-1]) $level--;
        
    // Wenn LFT < letztes RGT --> nach rechts
        
    elseif ($row['lft'] < $lastrgt$level++;
        if (
    $level) echo str_repeat('   '$level-1), ' |-';
        echo 
    ' '$row['wgruppen_name'], ' ( ID='$row['wgruppen_id'], ' )'"\n";
      }
      
    // Wenn Artikeldaten --> ausgeben
      // (soll ja in leeren Warengruppen kein "leerer" Artikel ausgeworfen werden!)
      
    if ($row['artikel_id'])
      {
        echo 
    str_repeat('   '$level), ' |-';
        echo 
    ' '$row['artikel_name'], ' ( ID='$row['artikel_id'], ' )'"\n";
      }
      
    $lastrgt $lvl2rgt[$level] = $row['rgt'];
    }
    echo 
    '</pre>'
    mein Sport: mein Frühstück: meine Arbeit:

    Sämtliche Code-Schnipsel sind im Allgemeinen nicht getestet und werden ohne Gewähr auf Fehlerfreiheit und Korrektheit gepostet.

    Kommentar


    • #3
      Vielen Dank für die Mühe

      Bis auf die fehlende Festlegung der zuletzt ausgegebenen WGruppen_ID funktioniert das so fehlerfrei. Zumindest konnte ich bisher mit ein paar Testeinträgen keine Fehler finden.

      Falls jemand diese Funktion benutzen sollte:

      nach

      $lastrgt = $lvl2rgt[$level] = $row['rgt'];

      noch

      $wgruppen_id=$row['wgruppen_id'];

      hinzufügen.

      Kannst du mir vielleicht noch erklären, wieso nach der Artikel_ID gruppiert wird? Ich habe es auch ohne dieser Gruppierung versucht, und es werden einige Einträge nicht angezeigt. Ich kann aber logisch nicht nachvollziehen, woran das liegt.

      Nochmals herzlichen Dank.

      Kommentar


      • #4
        Original geschrieben von plastikbaum
        Vielen Dank für die Mühe
        hab das nur eben in 5 minuten zusammengehäckselt. Ich wunder mich nur gerad, dass es keinen parse error gibt
        Kannst du mir vielleicht noch erklären, wieso nach der Artikel_ID gruppiert wird?
        Jetzt wo Du´s sagst ... Die "group by"-Klausel ist in diesem Fall tatsächlich überflüssig; nur wenn noch irgendein count auf eine andere Tabelle dazu käme, wäre sie nötig.
        Aber wenn group by, dann beide Felder! Sonst bekommst Du nur einen Artikel pro Warengruppe angezeigt.
        Ich habe es auch ohne dieser Gruppierung versucht, und es werden einige Einträge nicht angezeigt. Ich kann aber logisch nicht nachvollziehen, woran das liegt.
        Viel Erfolg bei der Suche. Eine Möglichkeit das heraus zu finden ist, die nicht angezeigten Datensätze umzubauen, bis sie angezeigt werden ... immer ein Feld nach dem anderen.

        Vielleicht fehlt aber einfach nur die Zuordnung?
        select a.*, z.artikel_id from tbl_artikel a left join tbl_zuordnung z on z.artikel_id=a.id having z.artikel_id is null
        mein Sport: mein Frühstück: meine Arbeit:

        Sämtliche Code-Schnipsel sind im Allgemeinen nicht getestet und werden ohne Gewähr auf Fehlerfreiheit und Korrektheit gepostet.

        Kommentar

        Lädt...
        X