kölir: aus gegebener Tabelle Menüstrutkur - Select

Hallo,

ich habe eine Tabelle vorgegeben:

root    -> Pfad
title    -> Seitentitel
order_id    -> sorgt für die Reihenfolge
content    -> Seiteninhalt

Nun soll ich daraus für einen gegebenen Pfad einen Array zusammenstellen, den man später für die Menüestellung verwenden kann.

z.B.: startseite/rechtliches
ist als Pfad vorgegeben, so soll ein Array erstellt werden, der Alle Elemente in der obersten Ebene enthält und an der richtigen Stelle die Verschachtelung. In etwa so:

startseite
startseite/rechtliches
startseite/rechtliches/teil-a
startseite/rechtliches/teil-b
kategorie-2
...

Nun habe ich bei dem Select hierfür und bei der zusammenfassung in einen Array, der auch noch richtig sortiert ist Probleme.

SELECT root, title
FROM tabelle
WHERE root NOT LIKE '%/%'    -> liefert Alle Elemente der obersten Ebene
    OR root LIKE 'pfad/%'
    AND root NOT LIKE 'pfad/%/%'    -> liefert Alle Elemente eine Ebene unter dem aktuellen

Doch wenn jetzt mein Pfad in ebene 4 ist habe ich mit dieser Abfrage natürlich ein Problem.

Und wie ich die Ergebnisse korrekt ordnen könnte weiß ich auch nicht.

Vielleicht hat jemand einen Denkanstoß

Gruß

  1. Hallo kölir,

    Und wie ich die Ergebnisse korrekt ordnen könnte weiß ich auch nicht.

    Vielleicht hat jemand einen Denkanstoß

    Ja, den habe ich, der wurde mir nämlich vor einem dreiviertel Jahr auch gegeben: "nested sets"

    http://forum.de.selfhtml.org/archiv/2007/6/t153764/

    Google bringt Dir entsprechende Anleitungen ...

    Grüße,
    luti

    1. Hallo,

      vielen Dank.
      Nested Sets habe ich sogar schon von gehört, aber die Tabelle besteht ja schon und ich soll diese verwenden

      Gruß

      1. Nested Sets habe ich sogar schon von gehört, aber die Tabelle besteht ja schon und ich soll diese verwenden

        Wer sagt das? Die Struktur ist denkbar ungeeignet ...

        Und wie ich die Ergebnisse korrekt ordnen könnte weiß ich auch nicht.

        Na, Du hast doch die Spalte order_id ?!? Wenn die für irgend etwas nützlich ist, dann füge doch einfach ORDER BY order_id in die Abfrage ein - wo ist das Problem?

        1. Hallo,

          aber die order_id bezieht sich immer nur auf die jeweilige Ebene.

          Gruß

          P.S.: Ich werd mal sehn, ob ich denjenigen nicht von Nested Sets überzeugen kann

          1. Hallo,

            habe nun das ganze auf Nested Sets umstellen könnnen!

            Habe ein kleines Problem bei meiner Abfrage:

            SELECT a.name, COUNT(*)-1 AS ebene
            FROM tabelle AS a, tabelle AS b
            WHERE a.lft BETWEEN b.lft AND b.rgt
            GROUP BY a.lft
            ORDER BY a.lft

            Das leifert mir ja den kompletten Baum, jetzt möchte ich aber ja eine Menüstruktur aufbauen, also brauche ich die oberste Ebene immer und dann die Ebenen bis zum aktuellen Element und eine ebene nach dem aktuellen Element.

            Doch wie erreiche ich das am besten? Die lft und rgt werte des aktuellen Elements sind bereits bekannt!

            Also theoretisch müssen die lft und rgt Werte entweder zwischen denen des aktuellen Elements liegen oder eben in der ersten Ebene liegen, aber damit fehlt mir ja u.U. auch der Baum bis zum aktuellen Element.

            Gruß

            1. P.S.:

              Ist das wie hier im letzten Beitrag beschrieben die Lösung?

              Aber wenn ich die Ebene mitspeicher ist doch des auch nichtmehr die elegante Art ...

              http://forum.de.selfhtml.org/archiv/2007/12/t163281/#m1063162

              Gruß

            2. echo $begrüßung;

              Das leifert mir ja den kompletten Baum, jetzt möchte ich aber ja eine Menüstruktur aufbauen, also brauche ich die oberste Ebene immer und dann die Ebenen bis zum aktuellen Element und eine ebene nach dem aktuellen Element.

              Wenn du stets sämtliche Elemente brauchst, um das Menü darzustellen, brauchst du nicht unbedingt Nested Sets. Nested Sets spielen dann ihre Vorteile aus, wenn man Teile der Baumstruktur in einzelnen Abfragen haben möchte. Solch eine Abfrage liefert die Daten aber auch nicht verschachtelt sondern "flach" zurück. In deiner Anwendung eine verschachtelte Struktur daraus aufzubauen bleibt dir nicht erspart, wenn du sowas benötigst.

              Ich gebe dir mal als Anregung für eine mögliche Alternative das Stichwort Serialized LOB-Pattern.

              Also theoretisch müssen die lft und rgt Werte entweder zwischen denen des aktuellen Elements liegen oder eben in der ersten Ebene liegen, aber damit fehlt mir ja u.U. auch der Baum bis zum aktuellen Element.

              Alle Nachkommen abzufragen ist sicher nicht das Problem. Nur alle eigenen Kinder haben zu wollen, ist ohne Ebenenangabe problematisch. Theoretisch wäre die Regel, dass das erste Kind lft = parent.lft+1 hat und die anderen lft = voriges_geschwister.right+1. Das bedeutete, dass man sich auf vorhergehende Datensätze beziehen können muss. Geht das mit vertretbarem Aufwand? Ich glaube nicht. Dann doch lieber die Ebene mitpflegen.

              Der Weg zur Wurzel sind alle Knoten, deren lft kleiner und deren rgt größer als das jeweils eigene ist.

              echo "$verabschiedung $name";

      2. echo $begrüßung;

        Nested Sets habe ich sogar schon von gehört, aber die Tabelle besteht ja schon und ich soll diese verwenden

        Menüdaten sind meist nur eine Handvoll Datensätze. Bei dir auch? Es ist ungünstig, rekursive Anfragen an die Datenbank abzusetzen, weil das einen nicht geringen Overhead nach sich zieht. Mit einer statischen Abfrage bist du in den Ebenen begrenzt. Wenn es sich wirklich nur um wenige Datensätze handelt, wäre mein Vorschlag, sie einfach so abzufragen, vielleicht schon vorsortiert, und die Struktur in der Anwendung zusammenzubauen.

        echo "$verabschiedung $name";

        1. Hi,

          ich schleich mich hier mal frech dazwischen, weil ich mich fuer dedlfix's Kommentar bzgl. Kosten von Rekursion interessiere ...

          dedlfix, beziehst du dich auf das "WITH ... AS" Konstrukt, das zumindest von DB2 und MSSQL 2005 standard-konform implementiert wurde, oder selbst geschriebene Rekursion auf der DB?

          Ich arbeite auch mit reichlich rekursiven Daten, die halt leider dynamisch sind ... ich habe mich fuer Rekursion entschieden ... eine schlechte Wahl deiner Meinung nach?

          'tschuldigung dass ich hier so reinplatze, aber thematisch passt das ja sehr gut.

          Danke

          1. echo $begrüßung;

            [...] Kommentar bzgl. Kosten von Rekursion [...]
            dedlfix, beziehst du dich auf das "WITH ... AS" Konstrukt, das zumindest von DB2 und MSSQL 2005 standard-konform implementiert wurde, oder selbst geschriebene Rekursion auf der DB?

            Letzteres, ersteres ist mir bis jetzt nicht bekannt gewesen. Abfragen einer Ergebnismenge und daraufhin mit Werten dieser Menge einzelne "Unter"anfragen auf das DBMS abzufeuern inklusive Ergebnisabholung, ist das, was sicher nicht besonders ressourcenschonend ist. Wenn das DBMS eine rekursive Abfrage intern verarbeiten kann, hat es hoffentlich ein paar Optimiermöglichkeiten. Es entsteht jedenfalls wenigstens nur einmal Overhead für eine Anfrage und einmal Ergebnisabholen.

            Ich arbeite auch mit reichlich rekursiven Daten, die halt leider dynamisch sind ... ich habe mich fuer Rekursion entschieden ... eine schlechte Wahl deiner Meinung nach?

            Das mag ich ohne Kenntnis des Systems oder Messergebnissen verschiedener Abfragevarianten nicht beurteilen.

            echo "$verabschiedung $name";

            1. Hi,

              danke fuer die Antwort.

              Rekursion direkt in SQL geht ueber sog. Common Table Expressions (CTE).

              -> http://msdn2.microsoft.com/en-us/library/ms175972.aspx

              Microsoft ausnahmsweise standard-konform, DB2 konnte das als erstes, ORACLE glaub ich (noch) nicht (Version 11?), Postgres fuer 8.4 geplant, glaub ich.

              Ich denke bei dynamischen Daten waere das die bessere Alternative.

              Was mich stoert an den nested sets sind die LOCK TABLES, das is halt echt schlecht.

              1. echo $begrüßung;

                Was mich stoert an den nested sets sind die LOCK TABLES, das is halt echt schlecht.

                Das braucht man nur bei der Datenpflege, nicht bei der Abfrage. Wenn die Daten oft geändert werden sollen, ist Nested Sets vielleicht nicht die beste Wahl. Eben wegen des hohen Verwaltungsaufwands. Bei wenigen Änderungen und vielen Abfragen nach Teilmengen können sie hingegen ihre Vorteile ausspielen.

                echo "$verabschiedung $name";