DBMS, z którym pracuję to MySQL, środowiskiem programistycznym jest Delphi 7 (co nie ma znaczenia dla tego przykładu).SQL i Delphi: mechanizm rekursywny do tworzenia drzewa z tabeli
Mam tabelę o nazwie "temat", w której przechowuję wszystkie książki w systemie. Przedmioty mogą mieć relacje rodzic-dziecko, podobnie jak nauka może być podzielona, powiedzmy, na matematykę i fizykę, podczas gdy matematyka może być podzielona na rachunek różniczkowy, algebrę, geometrię i dalej.
Chciałbym utworzyć drzewo z datą z tego stołu. Proszę, pomóż mi to zrobić. Nawet nie ma znaczenia, jakiego języka używa się do celów ilustracyjnych, po prostu może to być pseudokod.
Schemat bazy danych dla tabeli Temat wygląda następująco:
definicji tabeli Temat:
DROP TABLE IF EXISTS subject;
CREATE TABLE IF NOT EXISTS subject ( # Comment
subject_id INT UNSIGNED NOT NULL AUTO_INCREMENT, # Subject ID
subject VARCHAR(25) NOT NULL, # Subject name
parent_id INT UNSIGNED NULL DEFAULT NULL, # Parent ID as seen from
PRIMARY KEY (subject_id), # the diagram refers to
UNIQUE (subject), # the subject_id field
INDEX (parent_id),
CONSTRAINT fk_subject_parent
FOREIGN KEY (parent_id)
REFERENCES subject (subject_id)
ON DELETE RESTRICT
ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Zapełnianie tabeli tematów z jakiegoś manekina danych:
INSERT INTO subject (subject, parent_id) VALUES
('Science', NULL),
('Mathematics', 1),
('Calculus', 2),
('Algebra', 2),
('Geometry', 2),
('Languages', NULL),
('English', 6),
('Latin', 6);
Instrukcja SELECT zwraca to:
SELECT * FROM subject;
╔════════════╦═════════════╦═══════════╗
║ subject_id ║ subject ║ parent_id ║
╠════════════╬═════════════╬═══════════╣
║ 1 ║ Science ║ NULL ║
║ 2 ║ Mathematics ║ 1 ║
║ 3 ║ Calculus ║ 2 ║
║ 4 ║ Algebra ║ 2 ║
║ 5 ║ Geometry ║ 2 ║
║ 6 ║ Languages ║ NULL ║
║ 7 ║ English ║ 6 ║
║ 8 ║ Latin ║ 6 ║
╚════════════╩═════════════╩═══════════╝
Procedury składowane:
DELIMITER$$
DROP PROCEDURE IF EXISTS get_parent_subject_list;
CREATE PROCEDURE get_parent_subject_list()
BEGIN
SELECT subject_id, subject
FROM subject
WHERE parent_id IS NULL
ORDER BY subject ASC;
END$$
DROP PROCEDURE IF EXISTS get_child_subject_list;
CREATE PROCEDURE get_child_subject_list (IN parentID INT)
BEGIN
SELECT subject_id, subject
FROM subject
WHERE parent_id = parentID
ORDER BY subject ASC;
END$$
DELIMITER ;
Następny jest mój procedura Delphi, który próbuje zapełnić widok drzewa z danymi, ale jak widać dalej, że nie może dostać się głębiej niż drugi poziom :
procedure TForm1.CreateSubjectTreeView(Sender: TObject);
var
i : integer;
begin
i := 0;
q1.SQL.Clear;
q1.SQL.Add('CALL get_parent_subject_list()');
q1.Open;
q1.First;
while not q1.EOF do
begin
TreeView.Items.Add(nil, q1.Fields[1].Value);
q2.SQL.Clear;
q2.SQL.Add('CALL get_child_subject_list(' +
VarToStr(q1.Fields[0].Value) + ')');
q2.Open;
q2.First;
while not q2.EOF do
begin
TreeView.Items.AddChild(TreeView.Items.Item[i], q2.Fields[1].Value);
q2.Next;
end;
i := TreeView.Items.Count;
q1.Next;
end;
end;
to właśnie ten fragment kodu:
+- Science
| |
| +- Mathematics
|
+- Languages
|
+- English
+- Latin
Ale chciałbym to wyglądać tak:
+- Science
| |
| +- Mathematics
| |
| +- Calculus
| +- Algebra
| +- Geometry
|
+- Languages
|
+- English
+- Latin
+1 za dobrze uformowanej pytanie –
nie mogę pomóc w rozwiązaniu mysql, ale to, co szukasz jest hierarchicznych zapytań, a przykładem może można znaleźć tutaj: http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/ mysql nie ma klauzuli connect by, więc musiałbyś zrobić to ręcznie. –