Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.147 Beiträge
 
Delphi 12 Athens
 
#4

AW: Baumstruktur selber zeichnen

  Alt 4. Jul 2016, 14:33
Wenn dein DBMS rekursive SQL-Befehle kennt, dann kannst du für jeden Knoten zählen wie viele Eltern der hat und schon weißt du die Tiefe.

Außerdem fragst du das selber schon rekursiv ab, also mußt du dir nur merken in welcher Ebene du gerade bist und der aktuelle Knoten ist dann Eines tiefer.



Im Grunde kann man auch gleich DB-seitig die Ebene ermitteln und zusammen mit den Eltern alle Datensätze fertig sortiert ausgeben und muß dann nur noch in Ruhe zeichnen, ohne das über mehrere SELECTS abzufragen.




Ich hatte soeinen Code auch schonmal gesehn, wo man das Query auf CachedUpdate aktiviert hatte.
Dann nahm man sich einen Datensatz, ging per Locate so lange hoch, bis man keinen Elternknoten fand.
Danach dann rekursiv im selben Query per Locate die Kinder suchen und sie löschte, wenn eingefügt. (man könnte sich auch in einer Liste speichern, was schon verarbeitet wurde)
Und danach das wiederholen, bis es keine Datensätze mehr gibt. (das Letzte war, falls es Probleme in der Stuktur/Daten gibt, damit dann dennoch alles ausgegeben wird)





Ich hatte mir da auch or Kuzrem ein böses SELECT in Postgres geschrieben, um in einem DBGrid die selbe Reihenfolge zu haben, wie im TreeView.

SQL-Code:
SELECT
  sd_id, sd_name,
  sd_parentid,
  ...

  (SELECT array_to_string(array_agg(to_char(x_id, 'FM00009')), '-')::VARCHAR(250) FROM (
    WITH RECURSIVE temp (x_depth, x_id, x_parentid) AS (
      (SELECT 0, x.sd_id, x.sd_parentid
        FROM SettingsDyn AS x
        WHERE x.sd_id = SettingsDyn.sd_id
        UNION
        SELECT 666, 0, NULL) -- virtueller Wurzel-Knoten
      UNION ALL
      (SELECT x_depth+1, x.sd_id, x.sd_parentid
        FROM SettingsDyn AS x
        JOIN temp ON x_parentid = x.sd_id
        WHERE x_depth < 32)
    ) SELECT * FROM temp ORDER BY x_depth DESC
  ) AS temp) AS sd_order

FROM SettingsDyn
ORDER BY sd_order
[*] max(x_depth) ergäbe die Tiefe

SQL-Code:
(WITH RECURSIVE temp (x_depth, x_id, x_parentid) AS (
  (SELECT 0, x.sd_id, x.sd_parentid
    FROM SettingsDyn AS x
    WHERE x.sd_id = SettingsDyn.sd_id)
  UNION ALL
  (SELECT x_depth+1, x.sd_id, x.sd_parentid
    FROM SettingsDyn AS x
    JOIN temp ON x_parentid = x.sd_id
    WHERE x_depth < 32)
) SELECT max(x_depth) FROM temp) AS DieTiefe
[*] oder x_id gibt einfach ALLE Eltern zurück (hier inkl. sich selber), was man dann sonstwie kombinieren kann,
hier z.B. als ein String, der für die Sortierung nutzbar ist. (der Tree ist über die IDs sortiert, also stehen hier die IDs der Prarents in der richtigen Reihenfolge im String)

Code:
00000
00001
00001_00002
00001_00002_00003
00001_00004
00002
....
Hier könnte man auch auf x_depth verzichtgen und über Length(sd_order)/6 die Tiefe holen, falls/da man nur eine Spalte zurückgeben kann.
Sonst müsste man das besser in eine Funktion auslagern oder es als LATERAL JOIN anhängen.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 4. Jul 2016 um 14:38 Uhr)
  Mit Zitat antworten Zitat