powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Построить текстовую цепочку из дерева
51 сообщений из 51, показаны все 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
Построить текстовую цепочку из дерева
    #38945956
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadmanX11цепочка небольшая - 2-3 узла, длина поля name - 20 символов
Предлагаю пройтись дебаггером.

зацикливается на одном и тот же самом нижнем узле

PATH = APATH || '>' || PATH;
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945960
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wadman,

исправленный запрос.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
with recursive r (id, 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
Построить текстовую цепочку из дерева
    #38945961
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,

P.S. Забавно что объявлен домен INT. Что в сущности делать было вовсе не обязательно ибо у INTEGER и так есть псевдоним INT.
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945964
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
with recursive r (id, 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
Построить текстовую цепочку из дерева
    #38945965
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов ДенисА можешь дать немного данных для проверки?

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

OK. Добавил данные,нашёл ошибку. Вот исправленная версия

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
with recursive r (id, 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.id = r.parent
 where r.parent > 0
)
select
  list(name, '>') as path
from r
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945970
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11wadmanпропущено...

Предлагаю пройтись дебаггером.

зацикливается на одном и тот же самом нижнем узле

PATH = APATH || '>' || PATH;
Потому что нужно внимательнее переносить код.

X11
Код: sql
1.
2.
3.
4.
IF (AID IS NOT NULL) THEN
            SELECT ID, NAME FROM TYPES WHERE ID = :AID INTO :AID, :APATH;
        ELSE
            APATH = NULL;
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945980
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pid - это ID или PARENT?
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945990
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11pid - это ID или PARENT?
ID - id, PID - parent id.
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945991
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,

для пути в обратном порядке

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
with recursive r (id, parent, name, depth) as (
  select
    id, parent, name, 1
  from regions
  where id=187
  union all
  select
    regions.id,
    regions.parent,
    regions.name,
    r.depth + 1
 from r join regions on regions.id = r.parent
 where r.parent > 0
),
t as (
  select id, parent, name, depth
  from r
  order by depth desc
)
select
  list(name, '->') as path
from t



и соответственно ХП

Код: plsql
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.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
CREATE PROCEDURE GET_PATH (ID INT)
RETURNS (
    PATH BLOB SUB_TYPE TEXT)
AS
BEGIN
  FOR
      WITH RECURSIVE R (
          ID,
          PARENT,
          NAME,
          DEPTH)
      AS (SELECT
              ID,
              PARENT,
              NAME,
              1
          FROM
              REGIONS
          WHERE ID = :ID
          UNION ALL
          SELECT
              REGIONS.ID,
              REGIONS.PARENT,
              REGIONS.NAME,
              R.DEPTH + 1
          FROM
              R
              JOIN REGIONS ON REGIONS.ID = R.PARENT
          WHERE R.PARENT > 0),
      T
      AS (SELECT
              ID,
              PARENT,
              NAME,
              DEPTH
          FROM
              R
          ORDER BY DEPTH DESC)
      SELECT
          LIST(NAME, '->') AS PATH
      FROM
          T
      INTO PATH
  DO
    SUSPEND;
END
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945993
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
исправил

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
BEGIN
    SELECT PARENT, 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 <> 0) THEN
            SELECT PARENT, NAME FROM TYPES WHERE ID = :AID INTO :AID, :APATH;
        ELSE
            APATH = NULL;
    END
    IF (:PATH IS NOT NULL) THEN SUSPEND;
END



------ Performance info ------
Prepare time = 31ms
Execute time = 0ms

2 узла

в случае с рекурсией (другая таблица) 4 узла
------ Performance info ------
Prepare time = 47ms
Execute time = 0ms
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945995
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис
Код: plsql
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.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
CREATE PROCEDURE GET_PATH (ID INT)
RETURNS (
    PATH BLOB SUB_TYPE TEXT)
AS
BEGIN
  FOR
      WITH RECURSIVE R (
          ID,
          PARENT,
          NAME,
          DEPTH)
      AS (SELECT
              ID,
              PARENT,
              NAME,
              1
          FROM
              REGIONS
          WHERE ID = :ID
          UNION ALL
          SELECT
              REGIONS.ID,
              REGIONS.PARENT,
              REGIONS.NAME,
              R.DEPTH + 1
          FROM
              R
              JOIN REGIONS ON REGIONS.ID = R.PARENT
          WHERE R.PARENT > 0),
      T
      AS (SELECT
              ID,
              PARENT,
              NAME,
              DEPTH
          FROM
              R
          ORDER BY DEPTH DESC)
      SELECT
          LIST(NAME, '->') AS PATH
      FROM
          T
      INTO PATH
  DO
    SUSPEND;
END





------ Performance info ------
Prepare time = 32ms
Execute time = 0ms

ок

спасибо
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38945999
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Спасибо всем большое.
Буду использовать и рекурсию, и WHILE
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38946014
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
сделал 2 выборки из главной таблицы (1475 записей)

очень грубо, конечно, результаты:
select full_region from table1 и select full_type from table1


1. с использованием WHILE
План
PLAN (TYPES INDEX (PK_TYPES))(TYPES INDEX (PK_TYPES))
PLAN (A NATURAL)

------ Performance info ------
Prepare time = 31ms
Execute time = 0ms
Avg fetch time = 0,00 ms
Current memory = 9 809 144
Max memory = 9 849 408
Memory buffers = 2 048
Reads from disk to cache = 106
Writes from cache to disk = 0
Fetches from cache = 2 077


2. с использованием рекурсии
План
PLAN SORT ((T R REGIONS INDEX (PK_REGIONS))
PLAN (T R REGIONS INDEX (PK_REGIONS)))
PLAN (A NATURAL)

------ Performance info ------
Prepare time = 16ms
Execute time = 0ms
Avg fetch time = 0,00 ms
Current memory = 9 852 880
Max memory = 9 889 056
Memory buffers = 2 048
Reads from disk to cache = 9
Writes from cache to disk = 0
Fetches from cache = 2 497


с рекурсией быстрее
в таблице REGIONS глубина больше в 2 - 3 раза и записей на много больше, чем в таблице TYPES
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38946016
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11исправил
Как-то ты уж больно сложно исправил...
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
BEGIN
     SELECT PARENT, NAME FROM TYPES WHERE ID = :ID INTO :AID, :PATH;

     FOR SELECT PARENT, NAME FROM TYPES WHERE ID = :AID INTO :AID, :APATH DO
       BEGIN
         PATH = APATH || '>' || PATH;
       END
     SUSPEND;
END


Ты же, надеюсь, не собираешься скармливать этой процедуре ID-ы несуществующих записей,
PARENT имеет FK на ID и NAME у тебя объявлено как NOT NULL...
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38946018
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,

у рекурсии перед WHILE один недостаток она ограничена глубиной 1023. Ну обычно этого хватает
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38946030
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovТы же, надеюсь, не собираешься скармливать этой процедуре ID-ы несуществующих записей,
Я добавил в начало процедуры
Код: sql
1.
IF (:ID_REGION IS NULL) THEN EXIT;
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38946032
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovPARENT имеет FK на ID

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

у рекурсии перед WHILE один недостаток она ограничена глубиной 1023. Ну обычно этого хватает

ну такого количества 146% не будет, максимум до 10
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38946047
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11Dimitry SibiryakovPARENT имеет FK на ID

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

поскольку у тебя PARENT NOT NULL, то для добавления FK есть одна проблемка. Грубо говоря тебе придётся ввести корневую запись с ID 0. И в конце зациклить её на самой себя. Или же просто снять ограничение NOT NULL тогда FK добавить будет проще, но возможно придётся в других местах переделывать.
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38946347
Фотография S.G.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11Dimitry SibiryakovPARENT имеет FK на ID

такого нету
надо добавитьЭто надо сделать обязательно.


А для построения цепочки нет необходимости в рекурсии, только движение вверх по цепочке parent-ов,
и добавка новых имен "слева".
В псевдокоде:
1. Задано - ID начальное
2. Устанавливаем начальные значения:
PATH результат = '' - пустая строка, но не NULL
ID текущее = ID начальное
3. В цикле:
WHILE <ID текущее не есть корневое> DO
begin
- находим PARENT и NАМЕ текущего ID и записываем в
PARENT текущее, NAME текущее
- добавляем слева: PATH результат = NAME текущее + '->' + PATH результат
- ID текущее = PARENT текущее // движение "вверх"
end
4. Условие в WHILE не пропускает ID корневое, Поэтому,
после окончания цикла находим NAME текущее от последнего найденного PARENT текущее
(которое - корень) и добавляем в начало PATH результат.
5. убираем самую правую стрелку в результате.
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38947321
Фотография Tonal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня есть табличка с подобным деревом.
Материализованный путь там строится вот таким образом:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
select list(TITLE_EN, '>') as mpath from (
  with recursive
  PATH as (
    select 1 as REV_LEV, s.ID, s.PARENT_ID, s.TITLE_EN
    from SYMPTOMS s
    where ID = 11742
    union all
    select p.REV_LEV + 1, s2.ID, s2.PARENT_ID, s2.TITLE_EN
    from SYMPTOMS s2
    inner join PATH p on p.PARENT_ID = s2.ID
  )
  select * from PATH
  order by REV_LEV desc
)


Если заменить в этом запросе имя моей таблички SYMPTOMS на REGIONS , имена полей PARENT_ID и TITLE_EN на PARENT и NAME соответственно, то получится именно то, о чём тут просят.
И вроде бы без прохода по всей базе.
Ну и номер 11742 нужно заменить на параметр. :)
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38947337
Фотография Симонов Денис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Tonal,

это тоже самое что привёл я. Просто записано несколько в другом виде
...
Рейтинг: 0 / 0
Построить текстовую цепочку из дерева
    #38947356
Фотография Tonal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Симонов Денис.
Действительно. Вторую страничку не досмотрел...
...
Рейтинг: 0 / 0
51 сообщений из 51, показаны все 3 страниц
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Построить текстовую цепочку из дерева
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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