Einzelnen Beitrag anzeigen

omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: [MySQL] Stored Function für Zusammenstellung - wie?

  Alt 2. Apr 2006, 00:14
Hallo Panthrax,

dir ist klar, dass das keine triviale Aufgabe ist?
Wie dem auch sei, ich habe mich mal dran versucht.


Folgende Tabelle habe ich für den Baum angelegt...
SQL-Code:
CREATE TABLE `nodes` (
  `id` int(10) unsigned NOT NULL,
  `parentid` int(10) unsigned default NULL,
  `bez` varchar(45) NOT NULL default '',
  `reihenfolge` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY (`id`),
  KEY `FK_nodes_parentid` (`parentid`),
  CONSTRAINT `FK_nodes_parentid` FOREIGN KEY (`parentid`) REFERENCES `nodes` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Beispielinhalt...
SQL-Code:
+----+----------+-----+-------------+
| id | parentid | bez | reihenfolge |
+----+----------+-----+-------------+
| 1 | NULL | A | 1 |
| 2 | 1 | AA | 1 |
| 3 | 1 | AB | 2 |
| 4 | NULL | B | 2 |
| 5 | 4 | BA | 1 |
| 6 | 4 | BB | 2 |
| 7 | 1 | AC | 3 |
| 8 | 7 | ACA | 1 |
+----+----------+-----+-------------+
Dann habe ich folgende Prozedur angelegt...
SQL-Code:
CREATE PROCEDURE `proc_node`(IN _ParentID INT, IN _NurBlaetter BIT)
BEGIN
  DECLARE _done INT DEFAULT 0;
  DECLARE _id INT;
  DECLARE _bezeichnung VARCHAR(10);

  DECLARE cursor_nodes CURSOR FOR
    SELECT id, bez
    FROM nodes
    WHERE COALESCE(parentid, 0) = _ParentID
    ORDER BY reihenfolge;

  DECLARE CONTINUE HANDLER FOR SQLSTATE '02000SET _done = 1;
  OPEN cursor_nodes;

  REPEAT
    FETCH cursor_nodes INTO _id, _bezeichnung;
    IF _done = 0 THEN
      IF (SELECT COUNT(*) FROM nodes WHERE parentid = _id) = 0
         OR _NurBlaetter = 0
      THEN
        INSERT INTO temp (ID, Bezeichnung) VALUES (_id, _bezeichnung);
      END IF;
      CALL proc_node(_id, _NurBlaetter);
    END IF;
  UNTIL _done END REPEAT;

  CLOSE cursor_nodes;
END
und dann diese Prozedur...
SQL-Code:
CREATE PROCEDURE `proc_main`(IN _ParentID INT, IN _NurBlaetter BIT)
BEGIN
  SET @@max_sp_recursion_depth = 100;
  CREATE TEMPORARY TABLE temp (
    ID INT,
    Bezeichnung VARCHAR(10)
  );
  CALL proc_node(_ParentID, _NurBlaetter);
  SELECT *
  FROM temp;
  DROP TEMPORARY TABLE temp;
  SET @@max_sp_recursion_depth = 0;
END
Ausgabe des gesamten Baums...
SQL-Code:
CALL proc_main(0, 0);

+------+-------------+
| ID | Bezeichnung |
+------+-------------+
| 1 | A |
| 2 | AA |
| 3 | AB |
| 7 | AC |
| 8 | ACA |
| 4 | B |
| 5 | BA |
| 6 | BB |
+------+-------------+
Ausgabe aller Elemente und Unterelemente, die zum Element mit der ID = 1 gehören...
SQL-Code:
CALL proc_main(1, 0);

+------+-------------+
| ID | Bezeichnung |
+------+-------------+
| 2 | AA |
| 3 | AB |
| 7 | AC |
| 8 | ACA |
+------+-------------+
Ausgabe des gesamten Baums (nur die Blätter)...
SQL-Code:
CALL proc_main(0, 1);

+------+-------------+
| ID | Bezeichnung |
+------+-------------+
| 2 | AA |
| 3 | AB |
| 8 | ACA |
| 5 | BA |
| 6 | BB |
+------+-------------+
Ausgabe aller Blatt-Elemente, die zum Element mit der ID = 1 gehören...
SQL-Code:
CALL proc_main(1, 1);

+------+-------------+
| ID | Bezeichnung |
+------+-------------+
| 2 | AA |
| 3 | AB |
| 8 | ACA |
+------+-------------+
Wenn dein Baum sehr tief verschachtelt ist musst du eventuell die maximale Rekursionstiefe in proc_main erhöhen.

MfG
Thorsten

[edit=sakura] Auf Wunsch korrigiert. Mfg, sakura[/edit]
  Mit Zitat antworten Zitat