powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Построить текстовую цепочку из дерева
25 сообщений из 51, страница 1 из 3
Построить текстовую цепочку из дерева
    #38945842
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Приветствую всех.

Есть древовидный справочник.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
CREATE TABLE REGIONS (
    ID          "INT" NOT NULL /* "INT" = INTEGER */,
    PARENT      "INT" NOT NULL /* "INT" = INTEGER */,
    NAME        STRING50 NOT NULL COLLATE PXW_CYRL /* STRING50 = VARCHAR(50) */,
    CCOUNT      "INT" DEFAULT 0 NOT NULL /* "INT" = INTEGER */,
    SORTINDEX   "INT" DEFAULT 0 NOT NULL /* "INT" = INTEGER */,
    IMAGEINDEX  "INT" DEFAULT -1 NOT NULL /* "INT" = INTEGER */,
    STATEINDEX  "INT" DEFAULT -1 NOT NULL /* "INT" = INTEGER */,
    FULLPATH    STRING255 NOT NULL COLLATE PXW_CYRL /* STRING255 = VARCHAR(255) */);



Эта структура осталась ещё от купленных давно компонент FibExTree.
Менять не стал - удобно.

получается справочник районов, т.е. примерно так: Беларусь->Минск->Боровцы.

Таблица показывает пользователю только Боровцы.
Есть процедура на клиенте, которая строит указанную цепочку в Calculated поле, но хотелсь бы на сервере и максимально быстрый алгоритм.
В поле FULLPATH живёт вот такая цепочка "2775.141.2776.187.", т.е. цепочка из ID, 2775 - это корневой узел.

Помогите, пожалуйста, построить на сервере, но чтобы максимально быстро и эффективно тоже с использованием вычисляемого поля. Просто я боюсь, что напишу процедуру далеко не самую быструю.

Может быть уже есть готовые решения?

Спасибо.
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945843
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Забыл добавить: Firebird 2.5.4
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945847
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Индексы-то есть?
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945849
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11В поле FULLPATH живёт вот такая цепочка "2775.141.2776.187.", т.е. цепочка из ID, 2775 - это корневой узел.
Забавно... Корневой узел сделан позже, чем ветви. Перетаскивать можно или id с потолка взяты?
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945851
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Получается, что мне нужно сделать путь (path)
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945854
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadmanX11В поле FULLPATH живёт вот такая цепочка "2775.141.2776.187.", т.е. цепочка из ID, 2775 - это корневой узел.
Забавно... Корневой узел сделан позже, чем ветви. Перетаскивать можно или id с потолка взяты?

в программе есть возможность переносить выделенные узлы
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945855
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadman,

да, конечно, но это пока что неважно же
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945856
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот процедура путь добывает, но по именам.
Id = BigInt, varchar-ы тоже были доменными типами, переделал руками.
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
SET TERM ^ ;

create or alter procedure GET_OBJECT_PATH (
    ID ID)
returns (
    PATH VARCHAR(4096))
as
declare variable APATH VARCHAR(255);
declare variable AID type of ID;
begin
    select pid, name from object where id = :id into :aid, :apath;
    while (apath is not null) do begin
        if (path is not null) then
            path = apath || ' \ ' || path;
        else
            path = apath;
        if (aid is not null) then
            select pid, name from object where id = :aid into :aid, :apath;
        else
            apath = null;
    end
    if (:path is not null) then suspend;
end
^

SET TERM ; ^

COMMENT ON PROCEDURE GET_OBJECT_PATH IS
'Возвращает путь до объекта';

/* Following GRANT statetements are generated automatically */

GRANT SELECT ON OBJECT TO PROCEDURE GET_OBJECT_PATH;

...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945857
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сейчас пытаюсь вникнуть в CTE и рекурсивные запросы - надеюсь, на правильном пути. Но до сего момента не использовал и не имею представления об этом пока что ничего.
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945884
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот что у меня получилось

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
with recursive
        r as(
            select id, parent, name
            from regions
            where parent = 0

            union all

            select s.id, s.parent, r.name||'>'||s.name
            from regions s join r on s.parent=r.id
        )
        select name from r
        where r.id=187



http://www.sqlbooks.ru/printarticle.aspx?part=02&file=sql200509
14053226

правда, не сам допёр
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945894
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,

боюсь это далеко не самое эффективное решение. Ибо сначала будет построено дерево по всем записям, а только затем произойдёт фильтрация. Попробуй построить наоборот, т.е. от текущего узла к корню. Путь потом можно инвертировать функцией reverse
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945902
Фотография DarkMaster
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисПуть потом можно инвертировать функцией reverse

Та ну нафиг. 123-456 после REVERSE() 654-321 будет ;)
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945905
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисX11,

боюсь это далеко не самое эффективное решение. Ибо сначала будет построено дерево по всем записям, а только затем произойдёт фильтрация. Попробуй построить наоборот, т.е. от текущего узла к корню. Путь потом можно инвертировать функцией reverse

так я и строю от текущего, т.е. последнего узла к корню

Цепочка: "2775.141.2776.187.", 2775 - корень
я строю от 187
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945908
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисИбо сначала будет построено дерево по всем записям

Код: sql
1.
2.
3.
select id, parent, name
            from regions
            where parent = 0



только по корневым
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945910
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DarkMaster,

ммм... значит надо ещё подумать
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945911
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сейчас проблема вставить рекурсивный запрос в селективную хранимую процедуру

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
SET TERM ^ ;

create or alter procedure SP_GET_FULL_REGION (
    ID_REGION type of column REGIONS.ID)
as
declare variable RES varchar(1024) collate PXW_CYRL;
BEGIN
FOR SELECT NAME FROM
  (WITH RECURSIVE
        R AS(
            SELECT ID, PARENT, NAME
            FROM REGIONS
            WHERE PARENT = 0 OR (PARENT IS NULL)

            UNION ALL

            SELECT S.ID, S.PARENT, R.NAME||'>'||S.NAME
            FROM REGIONS S JOIN R ON S.PARENT=R.ID)
        SELECT SUBSTRING(NAME FROM 1 FOR 1024) NAME FROM R
        WHERE R.ID = :ID_REGION)

        INTO :RES
        DO


  SUSPEND;
END^

SET TERM ; ^



ничего не возвращает, т.е. процедура как бы не селективная получается
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945922
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11Вот что у меня получилось

если нужно действительно нужно отфильтровать только от корня то вот так

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
with recursive
        r as(
            select id, parent, name
            from regions
            where parent = 0 and id = 187

            union all

            select s.id, s.parent, r.name||'>'||s.name
            from regions s join r on s.parent=r.id
        )
        select name from r



будет эффективней. Ибо в рекурсивные запросы предикаты не проталкиваются
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945924
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денисесли нужно действительно нужно отфильтровать только от корня то вот так

нет, мне надо не от корня, а наоборот - от указанного текущего узла, и вверх до корня
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945927
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
и этот запрос пустой

Код: sql
1.
2.
3.
SELECT ID, PARENT, NAME
            FROM REGIONS
            WHERE PARENT = 0 and ID = 187



т.к. таких записей просто нет в таблице
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945931
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
чтобы легче было представить:





"ХАРЬКОВ>Город>САЛТОВКА>524м/р"

вот код

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
WITH RECURSIVE
        R AS(
            SELECT ID, PARENT, NAME
            FROM REGIONS
            WHERE PARENT = 0

            UNION ALL

            SELECT S.ID, S.PARENT, R.NAME||'>'||S.NAME
            FROM REGIONS S JOIN R ON S.PARENT=R.ID)
        SELECT SUBSTRING(NAME FROM 1 FOR 1024) NAME FROM R
        WHERE R.ID = 2780
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945939
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,

ну тогда надо разворачивать построение дерева. Я же говорю предикаты не проталкиваются. Будет построено дерево целиком и только потом к нему будет прилеплен фильтр. Т.е. по хорошему должно быть как-то так

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
with recursive r (code_horse, code_parent, name) as (
  select
    id, parent, name
  from regions
  where id=187
  union all
  select
    regions .id,
    regions.parent,
    regions.name
 from r join regions on regions.parent = r.id
 where r.parent > 0
)
select
  list(name, '>') as path
from r
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945940
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadman, Ваш код вызывает

Arithmetic overflow




SQL
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
SET TERM ^ ;

create or alter procedure SP_GET_FULL_TYPE (
    ID "INT")
returns (
    PATH STRING1000)
as
declare variable APATH varchar(255);
declare variable AID integer;
BEGIN
    SELECT ID, NAME FROM TYPES WHERE ID = :ID INTO :AID, :APATH;

    WHILE (APATH IS NOT NULL) DO BEGIN
        IF (PATH IS NOT NULL) THEN
            PATH = APATH || '>' || PATH;
        ELSE
            PATH = APATH;
        IF (AID IS NOT NULL) THEN
            SELECT ID, NAME FROM TYPES WHERE ID = :AID INTO :AID, :APATH;
        ELSE
            APATH = NULL;
    END
    IF (:PATH IS NOT NULL) THEN SUSPEND;
END^

SET TERM ; ^



цепочка небольшая - 2-3 узла, длина поля name - 20 символов
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945942
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис,

Код: sql
1.
with recursive r (code_horse, code_parent, name) as (...


копипаста от другого запроса должно быть так
Код: sql
1.
with recursive r (id, parent, name) as (...
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945947
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
with recursive r (code_horse, code_parent, name) as (
  select
    id, parent, name
  from regions
  where id=187
  union all
  select
    regions .id,
    regions.parent,
    regions.name
 from r join regions on regions.parent = r.id
 where r.parent > 0
)
select
  list(name, '>') as path
from r



твой код с ошибками

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
with recursive r (code_horse, code_parent, name) as (
  select
    id, parent, name
  from regions
  where id=187
  union all
  select
    regions .id,
    regions.parent,
    regions.name
 from r join regions on regions.parent = r.code_horse
 where code_parent > 0
)
select
  list(name, '>') as path
from r



и в результате вместо цепочки выдаёт только название текущего узла, где ID = 187
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945950
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11цепочка небольшая - 2-3 узла, длина поля name - 20 символов
Предлагаю пройтись дебаггером.
...
Рейтинг: 0 / 0
25 сообщений из 51, страница 1 из 3
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Построить текстовую цепочку из дерева
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]