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

vfedya
Дата: 04.12.2007 14:14:03
Имеем:
-дерево в таблице A(a.branchId, a.parentId, recId) около 10000
-таблицу атрибутов B (b.branchId, b.value, recId) около 140
Не все ветки дерева представлены в В. На ветки, которые не представлены в B, атрибут должен браться от branchId верхнего уровня.
Возможна также ситуация, когда в B указаны разные атрибуты для веток А1- атр1 и A1B2 атр2. Это значит, что на ветки А1А2... А1С2... распространяется атрибут атр1, а на ветви А1В2А3... -атр2.
Надо: всем a.branchId сопоставить b.value
Запрос типа
SELECT A.*, B.* From A, B
WHERE A.recid IN (select recid from A start with branchId =B.branchId
connect by prior branchId=parentId)
работает сравнительно долго, так что ограничение на LEVEL в подзапросе даже не пробовал.
Может у кого уже есть готовое решения?
dmidek
Дата: 04.12.2007 14:20:41
Пример исходных данных и желаемого результата был бы в помощь.
WITH / CREATE TABLE AS SELECT - скрипт тоже бы очень приветствовался...
Elic
Дата: 04.12.2007 14:26:59
Что-то вроде
substr(rtrim(sys_connect_by_path(b.value, '\'), '\'), instr(rtrim(sys_connect_by_path(b.value, '\'), '\'), '\', -1) + 1)
where b.branchId(+) = a.branchId
vfedya
Дата: 04.12.2007 15:40:08
Скриптов, к сожалению нет, таблицы в реале очень широкие...
Пример данных
TabA
branchId, parentId, recId
1 0 0
2 0 1
3 1 2
4 1 3
5 2 4
6 2 5
77 4 6

TabB
branchId, Value, recId
0 1 0
1 2 1
4 3 2

Результат:
branchId, Value
1 2
2 1
3 2
4 3
5 1
6 1
77 3
Zloxa
Дата: 04.12.2007 16:32:02
Elic - великий телепат, ни на символ не промазал, ни скобочкой не ошися. :)
SQL> with b as(
  2    select 1 branchId, 0 parentId, 0 recId from dual union all
  3    select 2, 0, 1 from dual union all
  4    select 3, 1, 2 from dual union all
  5    select 4, 1, 3 from dual union all
  6    select 5, 2, 4 from dual union all
  7    select 6, 2, 5 from dual union all
  8    select 77, 4, 6 from dual
  9   )
 10   ,v as(
 11    select 0 branchId, 1 Value, 0 recId  from dual union all
 12    select 1, 2, 1  from dual union all
 13    select 4, 3, 2  from dual
 14   )
 15  select b.branchId,to_number(substr(rtrim(sys_connect_by_path(nvl(v1.value,v2.value), '\'), '\')
 16                                     , instr(rtrim(sys_connect_by_path(nvl(v1.value,v2.value), '\'), '\'), '\', -1) + 1
 17                                     )
 18                              ) value
 19    from b,v v1,v v2
 20    where b.branchId = v1.branchId(+)
 21      and b.parentId = v2.branchId(+)
 22  start with parentId = 0
 23  connect by  prior b.branchID = parentId;
 
  BRANCHID      VALUE
---------- ----------
         1          2
         3          2
         4          3
        77          3
         2          1
         5          1
         6          1
 
7 rows selected
vfedya
Дата: 04.12.2007 16:43:01
Отлично! Спасибо, но завтра усложню задачу....
(если не найду сам решения).
Еще раз сенкс.
Elic
Дата: 05.12.2007 09:35:47
Zloxa
... nvl(v1.value,v2.value) ...
    from b,v v1
      ,v v2
    where b.branchId = v1.branchId(+)
      and b.parentId = v2.branchId(+)
Мсье извращенец?
Zloxa
Дата: 05.12.2007 09:53:00
Elic
Мсье извращенец?

В представленном наборе даных нарушена ссылочная целостность. Для TabA, корневой элемент branchId=0, отсутствует, но по TabB на него есть ссылки. Ссылочную целостность можно восстановить используя parentID.
Наверно можно и както иначе, интенсивно над этой проблемой не мыслил.
ModelR
Дата: 05.12.2007 09:58:16
Данные такие. Вроде
vfedya
Имеем:
-дерево в таблице A(a.branchId, a.parentId, recId) около 10000
ан корня 0 и нет:
vfedya
TabA
[quot vfedya]branchId, parentId, recId
1 0 0
2 0 1
3 1 2
4 1 3
5 2 4
6 2 5
77 4 6

Так или иначе надо извращаться.
with b as(
    select 1 branchId, 0 parentId, 0 recId from dual union all
    select 2, 0, 1 from dual union all
    select 3, 1, 2 from dual union all
    select 4, 1, 3 from dual union all
    select 5, 2, 4 from dual union all
    select 6, 2, 5 from dual union all
    select 77, 4, 6 from dual
    )
   ,v as(
   select 0 branchId, 1 Value, 0 recId  from dual union all
   select 1, 2, 1  from dual union all
   select 4, 3, 2  from dual
   )
  select b.branchId,to_number(substr(rtrim(sys_connect_by_path(v1.value, '\'), '\')
                                     , instr(rtrim(sys_connect_by_path(v1.value, '\'), '\'), '\', -1) + 1
                                     )
                              ) value
    from (select  branchId,  parentId, recId from b
            union 
            select 0, -1 ,-1 from dual 
          ) b,
          v v1
    where b.branchId = v1.branchId(+)
  start with parentId = -1
  connect by  prior b.branchID = parentId;
Elic
Дата: 05.12.2007 10:19:53
Zloxa
Elic
Мсье извращенец?
В представленном наборе даных нарушена ссылочная целостность. Для TabA, корневой элемент branchId=0, отсутствует, но по TabB на него есть ссылки. Ссылочную целостность можно восстановить используя parentID.
Наверно можно и както иначе, интенсивно над этой проблемой не мыслил.
Попробуй сняться с ручника и подумай, какую лажу ты написал :)