AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Baumstruktur darstellen

Ein Thema von Monday · begonnen am 1. Okt 2014 · letzter Beitrag vom 2. Okt 2014
Antwort Antwort
Monday

Registriert seit: 24. Aug 2012
103 Beiträge
 
FreePascal / Lazarus
 
#1

AW: Baumstruktur darstellen

  Alt 1. Okt 2014, 19:54
Vielen Dank für die Antworten.

Ich habe gebastelt und bin dem Ziel schon näher

Wenn man die Tiefe / Ebene (=ebene (wie sagt man da richtig bei einer baumstruktur!?)) mitspeichert, dann hat man ja schon fast die Strukur. Also gleich einrücken. Dann muss man nur noch die Zeilen richtig vertauschen.

Also soweit bin ich schon:

Ich habe jetzt eine DB mit der Struktur

id, parentID, tiefe, text

Das ganze lade ich erstmal in ein StringGrid und dann der Versuch der sortierung.

Auf einer Form habe ich ein StringGrid (m. Schriftart Courier wegen des Einrücken) mit mind. 4 Spalten und drei Buttons.

Relevant ist eigentlich nur die "Text" Spalte, in diesem Beispiel Spalte Nr. 3 (beginnend von 0). Die ersten drei id, parentID, tiefe sindnur hilfsspalten.

Nun sieht es so aus:

Code:

// http://www.delphi-treff.de/tipps-tricks/komponenten/tstringgrid/zeilen-in-einem-stringgrid-tauschen/
procedure ExchangeStringGridRows(const AGrid: TStringGrid; Row1, Row2: Integer);
var
  Temp: TStrings;
begin
  Temp:=TStringList.Create;
  try
    Temp.Assign(AGrid.Rows[Row1]);
    AGrid.Rows[Row1].Assign(AGrid.Rows[Row2]);
    AGrid.Rows[Row2].Assign(Temp);
  finally
    Temp.Free;
  end;
end;





procedure TForm1.Button1Click(Sender: TObject); // "sortieren"
var
  i, max,a: integer;
  leer : string;
begin
ZQuery1.SQL.Text := 'SELECT max(id) as max from daten;';
ZQuery1.Open;
max := ZQuery1.FieldByName('max').AsInteger;

   for i := 1 to max do begin // alle zellen durchgehen

     if StringGrid1.cells[2,i] <> '1' then begin // 1 ist die niedrigste Ebene
       // parentID / ID
       if (StringGrid1.cells[1,i] <> StringGrid1.cells[0,i-1]) and (StringGrid1.cells[1,i] <> StringGrid1.cells[1,i-1]) then begin
         ExchangeStringGridRows(StringGrid1, i, i-1);
       end;
     end;
end;


end;





procedure TForm1.Button2Click(Sender: TObject); // einlesen
var
  i, max: integer;
  leer : string;
begin
 ZQuery1.SQL.Text := 'SELECT max(id) as max from daten;';
 ZQuery1.Open;
 max := ZQuery1.FieldByName('max').AsInteger;

  ZQuery1.SQL.Text := 'select * from daten order by parentID asc, id desc, texta';
  ZQuery1.Open;


 for i := 1 to max do begin

   StringGrid1.Cells[0,i] := ZQuery1.FieldByName('id').AsString;;
   StringGrid1.Cells[1,i] := ZQuery1.FieldByName('parentID').AsString;;
   StringGrid1.Cells[2,i] := ZQuery1.FieldByName('tiefe').AsString;;

   if ZQuery1.FieldByName('tiefe').AsString = '1' then begin leer := ''; end;
   if ZQuery1.FieldByName('tiefe').AsString = '2' then begin leer := '  '; end;
   if ZQuery1.FieldByName('tiefe').AsString = '3' then begin leer := '     '; end;
   if ZQuery1.FieldByName('tiefe').AsString = '4' then begin leer := '        '; end;
   if ZQuery1.FieldByName('tiefe').AsString = '5' then begin leer := '           '; end;

   StringGrid1.Cells[3,i] := leer + ZQuery1.FieldByName('texta').AsString;;

   StringGrid1.RowCount:= StringGrid1.RowCount+1;
   ZQuery1.Next;
 end;


end;

procedure TForm1.Button3Click(Sender: TObject); // nur zum testen
var
  i: integer;
begin
 for i := 1 to 1500 do begin
  Button1Click(Self);     end;
end;

Im Prinzip funktioniert das schon. Allerdings gibts noch ein paar Probleme:
- er sortiert falsch bzw. es entsteht eine Endlosschleife
- sehr laaaaangsam



Lg
Monday


Edit: SQlite3

Geändert von Monday ( 1. Okt 2014 um 20:50 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Baumstruktur darstellen

  Alt 1. Okt 2014, 20:23
Welches Datenbanksystem?

SQlite?

Da geht das mit einer simplen Tabellenstruktur und einer netten Abfrage einfach so
SQL-Code:
CREATE TABLE org(
  name TEXT PRIMARY KEY,
  boss TEXT REFERENCES org
) WITHOUT ROWID;
INSERT INTO org VALUES('Alice',NULL);
INSERT INTO org VALUES('Bob','Alice');
INSERT INTO org VALUES('Cindy','Alice');
INSERT INTO org VALUES('Dave','Bob');
INSERT INTO org VALUES('Emma','Bob');
INSERT INTO org VALUES('Fred','Cindy');
INSERT INTO org VALUES('Gail','Cindy');

WITH RECURSIVE
  under_alice(name,level) AS (
    VALUES('Alice',0)
    UNION ALL
    SELECT org.name, under_alice.level+1
      FROM org JOIN under_alice ON org.boss=under_alice.name
     ORDER BY 2 DESC
  )
SELECT substr('..........',1,level*3) || name FROM under_alice;
ergibt dann
Code:
Alice
...Bob
......Dave
......Emma
...Cindy
......Fred
......Gail
http://www.sqlite.org/lang_with.html
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.877 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Baumstruktur darstellen

  Alt 1. Okt 2014, 20:42
Die Procedure sieht eher nac Interbase/Firebird aus.
Wenn es sich um FB handelt, könnte man auch eine CTE verwenden
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: Baumstruktur darstellen

  Alt 1. Okt 2014, 20:49
Die Procedure sieht eher nac Interbase/Firebird aus.
Wenn es sich um FB handelt, könnte man auch eine CTE verwenden
Jo, aber das kommt ja nicht vom TE, daher ist das noch völlig unklar, welche DB
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Monday

Registriert seit: 24. Aug 2012
103 Beiträge
 
FreePascal / Lazarus
 
#5

AW: Baumstruktur darstellen

  Alt 1. Okt 2014, 22:10
Ich habe es nur auf die schnelle ausprobiert. SQLite 3.8.0 kann es nicht, aber 3.8.7 kann es (und ich dachte immer x.x.x Versionen beinhalten keine großen Änderungen!).

Und was soll ich sagen?

Vielen vielen Dank für diesen Tipp!! Das sowas direkt in SQLite geht hätte ich mir nicht träumen lassen!!
Das ist so fantastisch, für den Code würde ich meine Frau eintauschen



Tausende von Datensätze schafft der in wenigen millisekunden. Ich behaupte mal, dass ich mehr Zeit benötige die Datensätze zu schreiben ^^

Da ist meine Tippserei ja gar nichts dagegen.

Vielen vielen Dank für die Hilfe!

Mal sehen ob es morgen immer noch funktioniert

LG,
Monday
  Mit Zitat antworten Zitat
taveuni

Registriert seit: 3. Apr 2007
Ort: Zürich
535 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Baumstruktur darstellen

  Alt 2. Okt 2014, 06:54
Das gibts auch bei MSSql inkl. Express Versionen ab Version 2008. Stichwort hierarchyid.
Die obige Aussage repräsentiert meine persönliche Meinung.
Diese erhebt keinen Anspruch auf Objektivität oder Richtigkeit.
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.487 Beiträge
 
Delphi 12 Athens
 
#7

AW: Baumstruktur darstellen

  Alt 2. Okt 2014, 12:40
Du solltest die Verknüpfung ID - ParentID (häufig gehört auch noch eine Position für die Reihenfolge dazu) auf jeden Fall in einer separaten DB-Tabelle speichern.
Sonst sperrt eine Verschiebung des Elements im Baum auch alle von der ID direkt oder indirekt abhängigen Datensätze.
Das verstehe ich nicht.
Wenn ich einen Knoten verschiebe, ändere ich nur seine Parent-ID. Was hat das mit den Unterknoten zu tun?
Fremdschlüssel von ParentID auf ID kann man innerhalt einer Tabelle vermutlich auch in diesem SQL-Dialekt nicht setzen.
Sollte ein Datensatz gelöscht werden, können immer noch Unterknoten existieren, die mit ParnetID auf den gelöschten Datensatz verweisen.

Das Problem "lock conflict ..." ist abhängig vom Transaktionsmanagment und betrifft z.B. Interbase oder Firebird.
Beispiel:
Die Baumstruktur enthält Artikel (Tabelle T_ARTIKEL Primärschlüssel ID).
Es gibt eine weitere Tabelle T_BESTELLUNG unter anderem mit dem Feld ArtikelID (mit Fremdschlüssel auf T_ARTIKEL.ID).
Der Artikel wird verändert (Bezeichnung, ParentID oder anderes) in Transaktion A.
Dadurch wird eine neue Version dieses Datensatzes erzeugt.
Andere Transaktionen z.B. B, die vor Ende der Transaktion A gestartet wurde, haben jetzt ein Problem.
Bestellungen die diesen Artikel enthalten, können in Transaktion B nicht gespeichert werden (lock conflict ...), da diese mit Fremdschlüssel(ArtikelID) auf die neue Version des Artikel-Datensatz verweisen müssen, der aber in Transaktion B noch nicht bekannt ist.
  Mit Zitat antworten Zitat
generic

Registriert seit: 24. Mär 2004
Ort: bei Hannover
2.416 Beiträge
 
Delphi XE5 Professional
 
#8

AW: Baumstruktur darstellen

  Alt 2. Okt 2014, 12:51
Das gibts auch bei MSSql inkl. Express Versionen ab Version 2008. Stichwort hierarchyid.
Alternativ geht das auch über CTE bei eigenen Datentypen.
Coding BOTT - Video Tutorials rund um das Programmieren - https://www.youtube.com/@codingbott
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:03 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz