Иерархический запрос

ORA-01489
Дата: 30.05.2006 13:55:02
Доброго времени суток!
Народ есть задачка:

есть иерархич запрос

select level, name1
from table1
start with prev_id is null
connect by id=prev_id

необходимо для каждой строки вывести головное имя....

Рассмотрела 2 варианта:
1) с SYS_CONNECT_BY_PATH() - вылетает когда строка большая
2) с подзапросом: select min(contract_id) KEEP(DENSE_RANK LAST ORDER BY(LEVEL) ... - работает оооочень медленно на реальных данных(большие иерархии level>200)

Как решить проблему?
dmidek
Дата: 30.05.2006 13:59:38
А где prior ?
Более подробно, плиз.
Можно и запросы показать ...
andrey_anonymous
Дата: 30.05.2006 14:08:02
ORA-01489
Как решить проблему?

Вы не указали сервер.
10 умеет connect_by_root.
ORA-01489
Дата: 30.05.2006 14:34:37
Сервер 9.2.0.6.0

Сами запросы:
1)
select
substr(SYS_CONNECT_BY_PATH(c.contract_number,'->'),3, instr(substr (SYS_CONNECT_BY_PATH(c.contract_number,'->'),3,90),'->')-1)
FROM contract c
where c.contract_prev_id is not null
START WITH c.contract_prev_id is null
CONNECT BY PRIOR c.contract_id = c.contract_prev_id
2)
select
(select min(contract_id) KEEP(DENSE_RANK LAST ORDER BY(LEVEL))
FROM contract c1
start with c1.contract_id = c.contract_id
connect by c1.contract_id = prior c1.contract_prev_id)
FROM contract c
where c.contract_prev_id is not null
START WITH c.contract_prev_id is null
CONNECT BY PRIOR c.contract_id = c.contract_prev_id
dmidek
Дата: 30.05.2006 15:22:37
ORA-01489


Сами запросы:
1)
select
substr(SYS_CONNECT_BY_PATH(c.contract_number,'->'),3, instr(substr (SYS_CONNECT_BY_PATH(c.contract_number,'->'),3,90),'->')-1)
FROM contract c
where c.contract_prev_id is not null
START WITH c.contract_prev_id is null
CONNECT BY PRIOR c.contract_id = c.contract_prev_id


Пока тупая попытка прорваться.
Вы используете как разделитель 2 символа "->". Это расточительство, Вы все равно их потом отрежете. Используете как разделитель 1 символ и может быть Ваша строка поместится в отведенные границы.
ORA-01489
Дата: 30.05.2006 15:36:53
dmidek
ORA-01489


Сами запросы:
1)
select
substr(SYS_CONNECT_BY_PATH(c.contract_number,'->'),3, instr(substr (SYS_CONNECT_BY_PATH(c.contract_number,'->'),3,90),'->')-1)
FROM contract c
where c.contract_prev_id is not null
START WITH c.contract_prev_id is null
CONNECT BY PRIOR c.contract_id = c.contract_prev_id


Пока тупая попытка прорваться.
Вы используете как разделитель 2 символа "->". Это расточительство, Вы все равно их потом отрежете. Используете как разделитель 1 символ и может быть Ваша строка поместится в отведенные границы.


Не надо так грубо(тупая попытка) - это не суть, хоть один символ - итог один и тот же - смысл в том что интересут только первый договор(максимум 10 символов, как бы обрезать строку, чтобы функция не вылетала, но похоже этого сделать нельзя), и вопрос еще и в том как это можно сделать иначе, т.е. варианты ...
dmidek
Дата: 30.05.2006 15:42:41
ORA-01489
dmidek
ORA-01489


Сами запросы:
1)
select
substr(SYS_CONNECT_BY_PATH(c.contract_number,'->'),3, instr(substr (SYS_CONNECT_BY_PATH(c.contract_number,'->'),3,90),'->')-1)
FROM contract c
where c.contract_prev_id is not null
START WITH c.contract_prev_id is null
CONNECT BY PRIOR c.contract_id = c.contract_prev_id


Пока тупая попытка прорваться.
Вы используете как разделитель 2 символа "->". Это расточительство, Вы все равно их потом отрежете. Используете как разделитель 1 символ и может быть Ваша строка поместится в отведенные границы.


Не надо так грубо(тупая попытка) - это не суть, хоть один символ - итог один и тот же - смысл в том что интересут только первый договор(максимум 10 символов, как бы обрезать строку, чтобы функция не вылетала, но похоже этого сделать нельзя), и вопрос еще и в том как это можно сделать иначе, т.е. варианты ...


ORA-01489, Вы меня совершенно неверно поняли.

"Тупая попытка" - это я так самокритично :) описал свою попытку решить Вашу проблему. Еще раз: попробуйте заменить 2 символа как разделитель на один (например /).
Тогда строка не будет такой большой.
andrey_anonymous
Дата: 30.05.2006 15:55:53
ORA-01489
варианты ...

С сомнением в голосе: попробуйте так...
SQL> with tab as (
select 1 id, null parent_id, 'parent1' value from dual union all
select 2 id, 1 parent_id, 'child 1->2' value from dual union all
select 3 id, 2 parent_id, 'child 1->2->3' value from dual union all
select 4 id, 5 parent_id, 'child 5->4' value from dual union all
select 5 id, null parent_id, 'parent5' value from dual union all
select 6 id, null parent_id, 'parent6' value from dual union all
select 7 id, 4 parent_id, 'child 4->7' value from dual union all
select 8 id, null parent_id, 'parent8' value from dual union all
select 9 id, 1 parent_id, 'child 1->9' value from dual union all
select 10 id, 2 parent_id, 'child 1->2->10' value from dual
)
select first_value(id) over(partition by grp order by parent_id nulls first) ROOT_ID,
       first_value(VALUE) over(partition by grp order by parent_id nulls first) ROOT_VALUE,
       t.Id, t.parent_id, t.value
from (select t.*,
              count(decode(parent_id, null, 1, null)) over(order by rownum) grp
       from (select level lvl, t.*, sys_connect_by_path(id, '->')
              from tab t
              connect by prior id = parent_id
              start with parent_id is null
            ) t
     ) t;

   ROOT_ID ROOT_VALUE             ID  PARENT_ID VALUE
---------- -------------- ---------- ---------- --------------
         1 parent1                 1            parent1
         1 parent1                 2          1 child 1->2
         1 parent1                 9          1 child 1->9
         1 parent1                 3          2 child 1->2->3
         1 parent1                10          2 child 1->2->10
         5 parent5                 5            parent5
         5 parent5                 7          4 child 4->7
         5 parent5                 4          5 child 5->4
         6 parent6                 6            parent6
         8 parent8                 8            parent8

10 rows selected

SQL> 
AlexOI
Дата: 30.05.2006 16:06:07
Попробуйте так

вместо

SYS_CONNECT_BY_PATH(c.contract_number,'->')

написать

replace(SYS_CONNECT_BY_PATH(case when level = 1 then c.contract_number else null end,'/'), '/')
Elic
Дата: 30.05.2006 16:06:45
ORA-01489
необходимо для каждой строки вывести головное имя....
1) с SYS_CONNECT_BY_PATH() - вылетает когда строка большая
replace(sys_connect_by_path(decode(level,1,contract_number),'-'), '-') as root
выдержит почти 4000 уровней.