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


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