Nested Set Baum Problem

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

  • Nested Set Baum Problem

    Hi,

    ich benutze derzeit eine Baumstruktur nach dem Nested Set Modell, will nun aber bei meiner Abfrage eine Spalte mit dem Inhalt "PARENT ID" ergänzen.
    Gibt es dazu eine sinnige Abfrage? Ich komm vielleicht einfach nur nicht auf den richigen Dreh. (Anm.: Vor der GROUP BY Funktion stehen die PARENT IDs noch in der Tabelle).

    Statement:

    Code:


    select * from nestedset a, nestedset b
    where a.left between b.left and b.right
    group by a.left


    Gruß Daniel

  • #2
    welcome.

    Wozu brauchst du die parent_id. das ist eigentlich viel mehr die frage...

    müsste aber einfach zu machen sein. allerdings nicht rein SQL-seitig, vermute ich. ist die frage was du haben willst.

    du machst dir eine abfrage mit id,left und right und speicherst das ganze in nem array. dann durch läufst du das array, und holst dir dabei die entsprechenden parents raus. bedingung dafür darfst du selbst überlegen

    Kommentar


    • #3
      Ganz einfach, ich hab die Struktur als Nested Set in der Datenbank und benutze aber einen JS-Tree (heißt glaub DTREE), der den Baum per Parentid aufbaut!
      Gruß Dani

      Kommentar


      • #4
        wenn du lft als parent_id haben willst ..

        Code:
        SELECT *, (
         SELECT IFNULL(MAX(link.lft), 0)
          FROM tree AS link
          LEFT JOIN tree AS parent ON (link.lft < parent.lft AND link.rgt > parent.rgt)
          WHERE parent.link = tree.link ) AS parent_id
         FROM tree;
        tabellennamen sind natürlich anzupassen ..
        Zuletzt geändert von Coragon Rivito; 05.08.2004, 20:07.
        mfg,
        [color=#0080c0]Coragon[/color]

        Kommentar


        • #5
          Ich glaub ich mach hier ein konkretes Beispiel für mein Problem, falls es noch jemand braucht und auch nicht gleich drauf kommt:

          Hier die Tabelle für die Sets (sorry ist grad für Oracle weil ich auf Arbeit bin, normalerweise benutze ich MySQL - sollte aber keinen Unterschied machen):

          Code:
          CREATE TABLE tree
              (id                             NUMBER(*,0) NOT NULL,
              left                           NUMBER(*,0) NOT NULL,
              right                          NUMBER(*,0) NOT NULL,
              title                          VARCHAR2(255) NOT NULL)
            PCTFREE     10
            PCTUSED     40
            INITRANS    1
            MAXTRANS    255
            TABLESPACE  eda_datastore
            STORAGE   (
              INITIAL     262144
              NEXT        262144
              PCTINCREASE 0
              MINEXTENTS  1
              MAXEXTENTS  2147483645
            )
          Hier die Einträge der Tabelle:

          Code:
          INSERT INTO tree
          (ID,LEFT,RIGHT,TITLE)
          VALUES
          (1,1,10,'root')
          /
          INSERT INTO tree
          (ID,LEFT,RIGHT,TITLE)
          VALUES
          (2,6,9,'cat2')
          /
          INSERT INTO tree
          (ID,LEFT,RIGHT,TITLE)
          VALUES
          (3,3,4,'entry1')
          /
          INSERT INTO tree
          (ID,LEFT,RIGHT,TITLE)
          VALUES
          (4,7,8,'entry2')
          /
          INSERT INTO tree
          (ID,LEFT,RIGHT,TITLE)
          VALUES
          (5,2,5,'cat1')
          /
          Und so sieht der Baum mit select aus:

          Code:
          select count(*) as depth, lpad(' ', 3*count(*))||a.title,a.id,a.left,a.right
          from tree a, tree b
          where a.left between b.left and b.right
          group by a.left,a.title,a.id,a.right
          Ausgabe:

          DEPTH LPAD('',3*COUNT(*))||A.TITLE ID LEFT RIGHT
          1 root 1 1 10
          2 cat1 5 2 5
          3 entry1 3 3 4
          2 cat2 2 6 9
          3 entry2 4 7 8


          --

          Und nun zum Ziel:
          Ich suche die gleiche Ausgabe wie oben, eben nur mit einer neuen Spalte namens parent_id, welche die ID des Elters / Vaters enthält.

          Wenn ich beim Select die group by funktion weglasse, bekomme ich ja eine Liste mit jedem Eintrag und seinen Eltern (dazu gehört auch der Eintrag selbst).

          --

          Der Select von Coragon (Danke!) machts möglich, und zwar werden für jeden Eintrag die Kinder gesucht. Sucht man nun nach einer Parentid für ein bestimmtes Kind, werden die entsprechenden Zeilen selektiert und die Zeile mit dem größten left-Wert ausgewählt. Bingo Danke!

          --

          Hier der Query für Oracle (irgendwie bin ich zu blöd für den Subselect ein GROUP BY attribut zu finden, also hab ich halt mit AVG aggregiert XD)
          Code:
          select c.left,c.title,AVG(
          (
          select MAX(a.left)
          from tree a, tree b
          where a. left < b.left and a.right > b.right
          and b.id = c.id
          )) parentid
          from tree c, tree d
          where c.left between d.left and d.right
          group by c.left,c.title
          Zuletzt geändert von mydani; 06.08.2004, 09:21.

          Kommentar


          • #6
            Nun hab ich noch folgendes problem,
            mit MySQL < 4.1 gehn keine Subquerys, also bin ich den Umweg über JOINS gegangen:

            Code:
            SELECT max(c.tree) PARENTID, a.*
            FROM tree a, tree b
            INNER JOIN tree c, tree d
            ON a.id = d.id
            WHERE a.left BETWEEN b.left and b.right
            AND c.left < d.left
            AND c.right > d.right
            GROUP BY a.left
            Was natürlich jetzt nicht mehr funktioniert ist der count(*), der vorher den Level angezeigt hat - es werden zuviele Zeilen gezählt (die Verknüpfung mit der c,d Tabelle dürfte das sein ) - gibts nen Weg diese Zeilen nicht mitzuzählen?

            Gruß Dani

            Kommentar


            • #7
              ich würde sagen, das ganze ist ja eine einmalige sache. speicher parentid in die db ung gut ist.

              Kommentar


              • #8
                Na, wenn du die Dynamik mal nicht vergisst - nimm mal an ich lösche nen Knoten oder verschiebe / tausche den.
                Dann muss ich die Parent IDs mitwarten, bei nem großen Baum kann das auch lästig werden.

                Kommentar


                • #9
                  nicht schlimmer als die lefts und rights zu warten.

                  Kommentar


                  • #10
                    Die muss ich ja sowieso warten, aber zusätzlich dann noch die Parents... Außerdem gibts da bestimmt ne passende Funktion bzw. Aggregation ... der Soll einfach den Count erst machen wenn das MAX vorbei ist *Argg*

                    Kommentar

                    Lädt...
                    X