Форум: "Основная";
Текущий архив: 2004.04.11;
Скачать: [xml.tar.bz2];
Вниззапрос к дереву Найти похожие ветки
← →
аппельсин (2004-03-24 13:16) [0]помогите написать запрос к таблице содержащей дерево.
необходимо организовать выборку всех ветвей с их потомками (и их потомками) начиная не от корня а с заданной ветви.
← →
Digitman © (2004-03-24 13:32) [1]за тебя запрос написать ? не зная структуры таблицы ?
← →
Романов Р.В. © (2004-03-24 13:35) [2]Я спросил у дерева... :)
← →
Vlad © (2004-03-24 13:37) [3]
> аппельсин (24.03.04 13:16)
Насколько мне известно, иерархические запросы поддерживает только Oracle (возможно MS SQL, хотя не уверен), в остальных случаях нужна рекурсивная процедура.
P.S. Тип СУБД слабо указать ?
← →
Романов Р.В. © (2004-03-24 13:39) [4]Рекурсивно составляй запросы к потомкам и на основе этих данных составляй запрос по всем элементам
← →
Курдль © (2004-03-24 13:42) [5]
> помогите написать запрос к таблице содержащей дерево
Если не на Оракле - то никогда не делайте этого!
Получите набор данных и в памяти его сортируйте, ровняйте, стройте, как хотите!
← →
Digitman © (2004-03-24 13:53) [6]есть и иной (достаточно простой) способ, который и безо всяких Ораклов позволит сформировать требуемый НД одним запросом, но при этом требуется вспомогательная таблица, хранящая инф-цию о дочерне-родительско-корневых связях узлов дерева
в этом случае в запросе будут участвовать обе таблицы
← →
Анонимщик © (2004-03-24 13:58) [7]См. http://ibase.ru/develop.htm
Там есть раздел
"Древовидные и иерархические структуры, хранение объектов"
← →
VLAD-MAL (2004-03-24 15:11) [8]Вот тебе таблица, содержащая дерево:
/*** Generated by IBExpert 24.03.2004 ***/
SET SQL DIALECT 3;
SET NAMES WIN1251;
/*** Tables ***/
CREATE GENERATOR PART_CATEGORY_ID_GEN;
CREATE TABLE PART_CATEGORY (
PART_CATEGORY_ID T_PART_CATEGORY_ID /* INTEGER */ NOT NULL,
BASE_PART_CATEGORY_ID T_BASE_PART_CATEGORY_ID /* INTEGER */ NOT NULL,
FNAME_SHORT T_FNAME_SHORT /* VARCHAR(84) */ NOT NULL,
LOCATION T_LOCATION /* INTEGER */,
CHILD_COUNT T_CHILD_COUNT /* INTEGER 1 NOT NULL */
);
/*** Primary Keys ***/
ALTER TABLE PART_CATEGORY ADD PRIMARY KEY (PART_CATEGORY_ID);
/*** Indices ***/
CREATE INDEX XIF154PART_CATEGORY ON PART_CATEGORY (BASE_PART_CATEGORY_ID);
/*** Triggers ***/
SET TERM ^ ;
/* Trigger: PART_CATEGORY_GEN_ID */
CREATE TRIGGER PART_CATEGORY_GEN_ID FOR PART_CATEGORY
ACTIVE BEFORE INSERT POSITION 0
as
begin
IF (new.Part_Category_id IS NULL) THEN
new.Part_Category_id = GEN_ID(Part_Category_id_gen, 1);
end
^
/* Trigger: PART_CATEGORY_TREE_BIUD */
CREATE TRIGGER PART_CATEGORY_TREE_BIUD FOR PART_CATEGORY
ACTIVE BEFORE INSERT OR UPDATE OR DELETE POSITION 99
as
BEGIN -- Категория товара - обеспечение фукционирования как дерева
if (inserting or updating) then begin
if (new.base_Part_Category_id is null) then
new.base_Part_Category_id = 0;
if (new.child_count is null) then
new.child_count = 0;
if (new.location is null) then -- Вполне достаточно для обеспечения последовательного размещения элементов
new.location = GEN_ID(Part_Category_id_gen, 1); -- при перемещении между уровнями можно просто сбросить значение Location
end
if ((inserting) or
(updating and
(old.Base_Part_Category_ID <> new.Base_Part_Category_ID)
)) then -- Увеличить счетчик детей у нового родителя
UPDATE Part_Category T SET T.CHILD_COUNT=T.CHILD_COUNT+1
WHERE T.Part_Category_ID = new.Base_Part_Category_ID;
if ((deleting) or
(updating and
(old.Base_Part_Category_ID <> new.Base_Part_Category_ID)
)) then -- Уменьшить счетчик детей у старого родителя
UPDATE Part_Category T SET T.CHILD_COUNT=T.CHILD_COUNT-1
WHERE T.Part_Category_ID = old.Base_Part_Category_ID;
if (deleting) then -- Каскадное удаление. Если не требуется, то перекрывается на клиенте
delete from Part_Category T
where
T.base_Part_Category_id = OLD.Part_Category_id;
END
^
/* Trigger: TD_PART_CATEGORY */
CREATE TRIGGER TD_PART_CATEGORY FOR PART_CATEGORY
ACTIVE AFTER DELETE POSITION 0
AS
DECLARE VARIABLE numrows INTEGER;
BEGIN
/* Part_Category описывает Part Запрет удаления родительской записи */
select count(*)
from Part
where
Part.part_category_id = OLD.part_category_id into numrows;
IF (numrows > 0) THEN
BEGIN
EXCEPTION CUSTOM_RESTRICT "Удалять нельзя: имеются записи в связанной таблице "Прайс"";
END
END
^
/* Trigger: TU_PART_CATEGORY */
CREATE TRIGGER TU_PART_CATEGORY FOR PART_CATEGORY
ACTIVE AFTER UPDATE POSITION 0
AS
DECLARE VARIABLE numrows INTEGER;
BEGIN
/* Part_Category описывает Part Запрет изменения родительской записи */
IF
(OLD.part_category_id <> NEW.part_category_id) THEN
BEGIN
select count(*)
from Part
where
Part.part_category_id = OLD.part_category_id into numrows;
IF (numrows > 0) THEN
BEGIN
EXCEPTION CUSTOM_RESTRICT "Изменять нельзя: имеются записи в связанной таблице "Прайс"";
END
END
END
^
SET TERM ; ^
Вот тебе процедура, возвращающая то, что надо:
CREATE PROCEDURE GET_TREE_PART_CATEGORY (
MASTER_PART_CATEGORY_ID INTEGER)
RETURNS (
PART_CATEGORY_ID INTEGER,
BASE_PART_CATEGORY_ID INTEGER,
FNAME_SHORT VARCHAR(84),
LOCATION INTEGER,
CHILD_COUNT INTEGER)
AS
begin
for select part_category_id, base_part_category_id, fname_short, location, child_count
from Part_Category T
where Base_Part_Category_id =:MASTER_Part_Category_id
order by T.Location, T.FName_Short
into :part_category_id, :base_part_category_id, :fname_short, :location, :child_count
do begin
suspend;
if (Child_Count > 0) then
for select part_category_id, base_part_category_id, fname_short, location, child_count
from get_tree_part_category(:Part_Category_id)
into :part_category_id, :base_part_category_id, :fname_short, :location, :child_count
do suspend;
end
end
Вот тебе процедура для контроля достоверности (в пределах дерева) вводимых данных
CREATE PROCEDURE GET_PARENTS_PART_CATEGORY (
ID INTEGER)
RETURNS (
DID INTEGER,
OID INTEGER)
AS
BEGIN
WHILE (ID > 0) DO
BEGIN
SELECT t.Part_Category_id, t.base_Part_Category_id
FROM Part_Category T
WHERE T.Part_Category_id = :ID
INTO :DID, :OID;
ID=OID;
SUSPEND;
END
END
PS - все сгенерировано by ErWin 4.1 для FireBird 1.5
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.04.11;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.04 c