Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 можно ли при помощи MODEL clause построить дерево?  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3778
+ данные
WITH t
     AS (SELECT 1 parent_id, 2 id FROM DUAL
         UNION ALL
         SELECT 1, 3 FROM DUAL
         UNION ALL
         SELECT 1, 4 FROM DUAL
         UNION ALL
         SELECT 1, 5 FROM DUAL
         UNION ALL
         SELECT 1, 6 FROM DUAL
         UNION ALL
         SELECT 2, 7 FROM DUAL
         UNION ALL
         SELECT 2, 8 FROM DUAL
         UNION ALL
         SELECT 2, 9 FROM DUAL
         UNION ALL
         SELECT 2, 10 FROM DUAL
         UNION ALL
         SELECT 2, 11 FROM DUAL
         UNION ALL
         SELECT 2, 12 FROM DUAL
         UNION ALL
         SELECT 7, 13 FROM DUAL
         UNION ALL
         SELECT 7, 14 FROM DUAL
         UNION ALL
         SELECT 7, 15 FROM DUAL
         UNION ALL
         SELECT 7, 16 FROM DUAL
         UNION ALL
         SELECT 3, 17 FROM DUAL
         UNION ALL
         SELECT 3, 18 FROM DUAL
         UNION ALL
         SELECT 1, 19 FROM DUAL
         UNION ALL
         SELECT 19, 20 FROM DUAL
         UNION ALL
         SELECT 19, 21 FROM DUAL
         UNION ALL
         SELECT 21, 22 FROM DUAL
         UNION ALL
         SELECT 7, 23 FROM DUAL)
    SELECT LPAD (' ', LEVEL * 2, ' ') || id, id, parent_id
      FROM t
CONNECT BY PRIOR id = parent_id
START WITH parent_id = 1
1 фев 12, 12:24    [12010154]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Vint
Member

Откуда: Москва
Сообщений: 4564
Андрей Панфилов,
можно то можно, но основной вопрос "нафига козе баян"?
1 фев 12, 12:26    [12010186]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3778
Vint,

чтобы представление сделать, в которое проталкиваются предикаты, с connect by так не сделать
1 фев 12, 12:32    [12010256]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
-2-
Member

Откуда:
Сообщений: 15330
Андрей Панфилов
чтобы представление сделать, в которое проталкиваются предикаты
а в какую часть model заталкиваются предикаты?
1 фев 12, 13:01    [12010610]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
Андрей Панфилов
Vint,

чтобы представление сделать, в которое проталкиваются предикаты, с connect by так не сделать

connect by разные бывают.
если версия позволяет - на 11.2 refactoring посмотрите
1 фев 12, 13:28    [12010953]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3778
-2-
а в какую часть model заталкиваются предикаты?
Partition columns define the logical blocks of the result set in a way similar to the partitions of the analytical functions described in Chapter 21, "SQL for Analysis and Reporting". Rules in the MODEL clause are applied to each partition independent of other partitions. Thus, partitions serve as a boundary point for parallelizing the MODEL computation.

orawish,
10g
1 фев 12, 14:06    [12011523]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
andrey_anonymous
Member

Откуда: Москва
Сообщений: 18337
Что-то понакрутил я тут... Упрощайте, кто в силах :)
select l, id, parent_id 
from t
model
dimension by (id, row_number() over(order by id) r)
measures (cast(null as varchar2(100)) l, parent_id, 1 lvl, cast(null as varchar2(100)) ord)
ignore NAV
RULES SEQUENTIAL ORDER iterate (1000) until previous(lvl[0,0]) = lvl[0,0]
(lvl[any,any] order by id,r = nvl(min(lvl)[parent_id[cv(),cv()],any],0) + 1 -- крутим level, по сути это можно попробовать объединить с ord
,  l[any,any] order by id,r = lpad(' ',lvl[cv(),cv()]*2,' ')||cv(id) -- lpad, можно сделать непосредственно в  select list
, ord[any,any] order by id,r = min(ord)[parent_id[cv(),cv()],any] || '-' ||cv(r) -- порядок сортировки
, lvl[0,0] = nvl(max(lvl)[any,r <> 0],0) -- условие для iterate until, который не понимает агрегатов
)
order by ord
1 фев 12, 18:14    [12014441]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 837
Андрей Панфилов
чтобы представление сделать, в которое проталкиваются предикаты, с connect by так не сделать
Деревья можно обходить помимо connect by еще recursive with or model, но последние два способа совершенно не взлетают.
Все варианты можно найти здесь: 10199825
С графами ситуация несколько иная.
Но что ты хочешь "протолкнуть" до конца неясно. Where clause не помогает?

Кстати, есть ли у кого желание послушать что-то в духе "Работа с деревьями и графами в Oracle" на RuOUG, а то у меня имеется определенный черновичок.
1 фев 12, 19:52    [12015043]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Elic
Member

Откуда:
Сообщений: 29976
Кобанчег
Но что ты хочешь "протолкнуть" до конца неясно.
Я мог бы увидеть смысл только в START WITH + соответствующий CONNECT_BY_ROOT.
1 фев 12, 19:59    [12015067]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
orawish
Member

Откуда: Гадюкино-2 (City)
Сообщений: 15487
Андрей Панфилов,

кстати, а pipelined не устроит?
1 фев 12, 20:15    [12015130]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 837
Elic,

Это да. Ну тут еще спасает:
, table(select collect(<col>) from <tbl> where <condition>)
, table(cast(multiset(select <col> from <tbl> where <condition>)

Вот только термин "проталкивание предикатов" сюда несколько не в тему.
1 фев 12, 20:24    [12015160]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3778
Кобанчег,

таблица:

id документа id родителя id поручения
:
id родителя - либо сам документ, либо поручение по документу

цель - посроить дерево поручений по документу с указанным id, движок приложения из SQL умеет только INNER JOIN и простые условия на поля: field = value, field in (values), field in (select values), решение - сделать вьюху. Вот такой запрос во вьюху не засунуть так, чтобы он сначала отобрал все записи с требуемым document_id, а потом построил дерево
WITH t
     AS (SELECT 1 AS document_id, 1 AS parent_id, 2 AS order_id FROM DUAL
         UNION ALL
         SELECT 1, 1, 3 FROM DUAL
         UNION ALL
         SELECT 1, 1, 4 FROM DUAL
         UNION ALL
         SELECT 1, 2, 5 FROM DUAL
         UNION ALL
         SELECT 1, 2, 6 FROM DUAL
         UNION ALL
         SELECT 1, 2, 7 FROM DUAL
         UNION ALL
         SELECT 9, 9, 8 FROM DUAL)
    SELECT LPAD (' ', LEVEL * 2, ' ') || order_id, document_id
      FROM t
CONNECT BY PRIOR order_id = parent_id
START WITH parent_id = document_id AND parent_id = 1
1 фев 12, 20:49    [12015241]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 837
Андрей Панфилов
движок приложения из SQL умеет только INNER JOIN и простые условия на поля: field = value, field in (values), field in (select values), решение - сделать вьюху.
Во-первых странные ограничения порождают странные решения. Элик вроде как стелепатировал твой вопрос и я сообщением выше дал ответ.
Для твоего примера:
WITH t
     AS (SELECT 1 AS document_id, 1 AS parent_id, 2 AS order_id FROM DUAL
         UNION ALL
         SELECT 1, 1, 3 FROM DUAL
         UNION ALL
         SELECT 1, 1, 4 FROM DUAL
         UNION ALL
         SELECT 1, 2, 5 FROM DUAL
         UNION ALL
         SELECT 1, 2, 6 FROM DUAL
         UNION ALL
         SELECT 1, 2, 7 FROM DUAL
         UNION ALL
         SELECT 9, 9, 8 FROM DUAL),
ids as (select 1 id from dual)
select ids.id,
       substr(column_value,1,instr(column_value,chr(1))-1) order_id,
       substr(column_value,instr(column_value,chr(1))+1) document_id
from ids,
table(cast(multiset(
SELECT LPAD (' ', LEVEL * 2, ' ') || order_id || chr(1) || document_id
  FROM t
CONNECT BY PRIOR order_id = parent_id
START WITH parent_id = document_id AND parent_id = ids.id
) as sys.ku$_vcnt));

        ID ORDER_ID   DOCUMENT_I
---------- ---------- ----------
         1   2        1
         1     5      1
         1     6      1
         1     7      1
         1   3        1
         1   4        1

6 rows selected.
Вариант с "table(select collect(<col>) from <tbl> where <condition>)" можешь попробовать сам.

Но если у тебя есть возможность передавать список и делать in (...), то построй деревья, стартуя из списка, и ты всегда можешь знать из какого эл-та построено конкретное дерево в результирующем наборе с помощью CONNECT_BY_ROOT как тоже было сказано выше.
1 фев 12, 21:13    [12015333]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3778
Кобанчег,

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

то что прикладуха не умеет оракловые фичи - это плата за поддержку нескольких СУБД
1 фев 12, 21:22    [12015374]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 837
Андрей Панфилов
чтобы передать нужный идентификатор его нужно куда-то записать
Появляются все новые и новые "интересные" ограничения.
Я показал как построить дерево, при этом "передать" туда дополнительное условие.
Андрей Панфилов
то что прикладуха не умеет оракловые фичи - это плата за поддержку нескольких СУБД
Тогда зачем спрашивать про model?
1 фев 12, 21:26    [12015393]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3778
Кобанчег
Я показал как построить дерево, при этом "передать" туда дополнительное условие
где? with ids as (select 1 id from dual) - никакого отношения к "движок приложения из SQL умеет только INNER JOIN и простые условия на поля: field = value, field in (values), field in (select values), решение - сделать вьюху." не имеет

Кобанчег
Тогда зачем спрашивать про model?
create or replace view xxx as
select ...
model
partition by (document_id)
...

select * from xxx where document_id=...
так понятнее?
1 фев 12, 21:36    [12015464]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Кобанчег
Member

Откуда: Рахів
Сообщений: 837
Андрей Панфилов
Кобанчег
Я показал как построить дерево, при этом "передать" туда дополнительное условие
где? with ids as (select 1 id from dual) - никакого отношения к "движок приложения из SQL умеет только INNER JOIN и простые условия на поля: field = value, field in (values), field in (select values), решение - сделать вьюху." не имеет
Прости меня, пожалуйста, что я не стелепатировал как там твоя прикладуха работает.
Если тебе остро надо создать view содержащее start with, то в нем ты ясное дело в start with ничего не протолкнешь.
Разве что это, но оно противоречит твоему желанию что-то куда-то записывать.
create global temporary table t_tmp(id int);

create or replace view v as
WITH t
     AS (SELECT 1 AS document_id, 1 AS parent_id, 2 AS order_id FROM DUAL
         UNION ALL
         SELECT 1, 1, 3 FROM DUAL
         UNION ALL
         SELECT 1, 1, 4 FROM DUAL
         UNION ALL
         SELECT 1, 2, 5 FROM DUAL
         UNION ALL
         SELECT 1, 2, 6 FROM DUAL
         UNION ALL
         SELECT 1, 2, 7 FROM DUAL
         UNION ALL
         SELECT 9, 9, 8 FROM DUAL)
    SELECT LPAD (' ', LEVEL * 2, ' ') || order_id order_id, document_id, connect_by_root parent_id root_parent
      FROM t
CONNECT BY PRIOR order_id = parent_id
START WITH parent_id = document_id AND parent_id = (select * from t_tmp);

insert into t_tmp select rownum from dual;

select * from v;
1 фев 12, 22:02    [12015570]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
stax..
Guest
Кобанчег
Андрей Панфилов
чтобы представление сделать, в которое проталкиваются предикаты, с connect by так не сделать
Деревья можно обходить помимо connect by еще recursive with or model, но последние два способа совершенно не взлетают.
Все варианты можно найти здесь: 10199825
С графами ситуация несколько иная.
Но что ты хочешь "протолкнуть" до конца неясно. Where clause не помогает?

Кстати, есть ли у кого желание послушать что-то в духе "Работа с деревьями и графами в Oracle" на RuOUG, а то у меня имеется определенный черновичок.

не подскажете как с помощью рекурсиного with смоделировать connect_by_isleaf
для дерева (можна на примере емр)?

чет я проморгал

.....
stax
2 фев 12, 17:34    [12021407]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Сергей Арсеньев
Member

Откуда:
Сообщений: 4118
stax..
не подскажете как с помощью рекурсиного with смоделировать connect_by_isleaf
для дерева (можна на примере емр)?

+ на emp сложно
with t as (
 select 1 id, null parent from dual
  union all
 select 2,1 from dual
  union all
 select 3,2 from dual
  union all
 select 4,1 from dual
)
, conn (id,parent,lvl,root,prnt) as (
 select t1.id,t1.parent,1 lvl,id root,null prnt from t t1
union all
 select t2.id,c.id,c.lvl+1,c.root,c.parent prnt from t t2
  join conn c on (c.id=t2.parent(+) and c.id is not null)
) search depth first by id set a
select id,parent,root,leaf from (select c.*,decode(lead(id) over (order by c.a),null,1,0) leaf from conn c)
 where id is not null
2 фев 12, 18:51    [12021991]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
stax..
Guest
[b][/b]
Сергей Арсеньев
stax..
не подскажете как с помощью рекурсиного with смоделировать connect_by_isleaf
для дерева (можна на примере емр)?

+
+ на emp сложно
with t as (
 select 1 id, null parent from dual
  union all
 select 2,1 from dual
  union all
 select 3,2 from dual
  union all
 select 4,1 from dual
)
, conn (id,parent,lvl,root,prnt) as (
 select t1.id,t1.parent,1 lvl,id root,null prnt from t t1
union all
 select t2.id,c.id,c.lvl+1,c.root,c.parent prnt from t t2
  join conn c on (c.id=t2.parent(+) and c.id is not null)
) search depth first by id set a
select id,parent,root,leaf from (select c.*,decode(lead(id) over (order by c.a),null,1,0) leaf from conn c)
 where id is not null


спасибо

в жизнь бы не догадался поставить (+)

join conn c on (c.id=t2.parent(+) and c.id is not null)


.....
stax
2 фев 12, 19:10    [12022065]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
Андрей Панфилов
Member

Откуда: Москва > Melbourne
Сообщений: 3778
andrey_anonymous,

Спасибо, то что нужно, и проталкивается куда нужно
13 фев 12, 15:40    [12082346]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10042
Сергей Арсеньев
на emp сложно


Начиная с 11.2.0.2.0 проще:

SQL> select  *
  2    from v$version
  3  /

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE    11.2.0.2.0      Production
TNS for HPUX: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production

WITH StartWith(
               Ename,
               Empno,
               Mgr,
               Seq,
               EnamePath,
               EmpnoPath,
               LevelNum
              ) AS (
                     -- First part of union gets "starting" records
                     SELECT  Ename,
                             Empno,
                             Mgr,
                             TO_CHAR(row_number() over(order by Empno)) As Seq,
                             Ename As EnamePath,
                             TO_CHAR(Empno) As EmpnoPath,
                             1 As LevelNum
                       FROM  EMP 
                       WHERE  Mgr IS NULL
                    UNION ALL
                     -- Second part of query "chains" to employees under the manager
                       SELECT  e.Ename,
                               e.Empno,
                               e.Mgr,
                               s.Seq || '.' || row_number() over(order by e.Empno) As Seq,
                               s.EnamePath || ',' || e.Ename As EnamePath,
                               s.EmpnoPath || ',' || s.Empno As EmpnoPath,
                               s.LevelNum + 1 As LevelNum
                         FROM  EMP  e INNER JOIN StartWith s  ON s.Empno = e.Mgr 
              )
              SEARCH DEPTH FIRST BY empno SET order1
SELECT  lpad(' ',LevelNum - 1) || Ename Ename,
        Empno,
        Mgr,
        LevelNum,
        Seq,
        EnamePath,
        EmpnoPath,
        CASE
          WHEN LEAD(LevelNum,1,LevelNum) OVER(ORDER BY Seq) <= LevelNum THEN 1
          ELSE 0
        END IsLeaf
  FROM  StartWith
  ORDER BY order1
/


ENAME           EMPNO        MGR   LEVELNUM SEQ        ENAMEPATH              EMPNOPATH                  ISLEAF
---------- ---------- ---------- ---------- ---------- ---------------------- ---------------------- ----------
KING             7839                     1 1          KING                   7839                            0
 JONES           7566       7839          2 1.1        KING,JONES             7839,7839                       0
  SCOTT          7788       7566          3 1.1.4      KING,JONES,SCOTT       7839,7839,7566                  0
   ADAMS         7876       7788          4 1.1.4.2    KING,JONES,SCOTT,ADAMS 7839,7839,7566,7788             1
  FORD           7902       7566          3 1.1.7      KING,JONES,FORD        7839,7839,7566                  0
   SMITH         7369       7902          4 1.1.7.1    KING,JONES,FORD,SMITH  7839,7839,7566,7902             1
 BLAKE           7698       7839          2 1.2        KING,BLAKE             7839,7839                       0
  ALLEN          7499       7698          3 1.2.1      KING,BLAKE,ALLEN       7839,7839,7698                  1
  WARD           7521       7698          3 1.2.2      KING,BLAKE,WARD        7839,7839,7698                  1
  MARTIN         7654       7698          3 1.2.3      KING,BLAKE,MARTIN      7839,7839,7698                  1
  TURNER         7844       7698          3 1.2.5      KING,BLAKE,TURNER      7839,7839,7698                  1

ENAME           EMPNO        MGR   LEVELNUM SEQ        ENAMEPATH              EMPNOPATH                  ISLEAF
---------- ---------- ---------- ---------- ---------- ---------------------- ---------------------- ----------
  JAMES          7900       7698          3 1.2.6      KING,BLAKE,JAMES       7839,7839,7698                  1
 CLARK           7782       7839          2 1.3        KING,CLARK             7839,7839                       0
  MILLER         7934       7782          3 1.3.8      KING,CLARK,MILLER      7839,7839,7782                  1

14 rows selected.

SQL> 

WITH StartWith(
               Ename,
               Empno,
               Mgr,
               Seq,
               EnamePath,
               EmpnoPath,
               LevelNum
              ) AS (
                     -- First part of union gets "starting" records
                     SELECT  Ename,
                             Empno,
                             Mgr,
                             TO_CHAR(row_number() over(order by Empno)) As Seq,
                             Ename As EnamePath,
                             TO_CHAR(Empno) As EmpnoPath,
                             1 As LevelNum
                       FROM  EMP 
                       WHERE  Mgr IS NULL
                    UNION ALL
                     -- Second part of query "chains" to employees under the manager
                       SELECT  e.Ename,
                               e.Empno,
                               e.Mgr,
                               s.Seq || '.' || row_number() over(order by e.Empno) As Seq,
                               s.EnamePath || ',' || e.Ename As EnamePath,
                               s.EmpnoPath || ',' || s.Empno As EmpnoPath,
                               s.LevelNum + 1 As LevelNum
                         FROM  EMP  e INNER JOIN StartWith s  ON s.Empno = e.Mgr 
              )
              SEARCH BREADTH FIRST BY empno SET order1
SELECT  lpad(' ',LevelNum - 1) || Ename Ename,
        Empno,
        Mgr,
        LevelNum,
        Seq,
        EnamePath,
        EmpnoPath,
        CASE
          WHEN LEAD(LevelNum,1,LevelNum) OVER(ORDER BY Seq) <= LevelNum THEN 1
          ELSE 0
        END IsLeaf
  FROM  StartWith
  ORDER BY order1
/

ENAME           EMPNO        MGR   LEVELNUM SEQ        ENAMEPATH              EMPNOPATH                  ISLEAF
---------- ---------- ---------- ---------- ---------- ---------------------- ---------------------- ----------
KING             7839                     1 1          KING                   7839                            0
 JONES           7566       7839          2 1.1        KING,JONES             7839,7839                       0
 BLAKE           7698       7839          2 1.2        KING,BLAKE             7839,7839                       0
 CLARK           7782       7839          2 1.3        KING,CLARK             7839,7839                       0
  ALLEN          7499       7698          3 1.2.1      KING,BLAKE,ALLEN       7839,7839,7698                  1
  WARD           7521       7698          3 1.2.2      KING,BLAKE,WARD        7839,7839,7698                  1
  MARTIN         7654       7698          3 1.2.3      KING,BLAKE,MARTIN      7839,7839,7698                  1
  SCOTT          7788       7566          3 1.1.4      KING,JONES,SCOTT       7839,7839,7566                  0
  TURNER         7844       7698          3 1.2.5      KING,BLAKE,TURNER      7839,7839,7698                  1
  JAMES          7900       7698          3 1.2.6      KING,BLAKE,JAMES       7839,7839,7698                  1
  FORD           7902       7566          3 1.1.7      KING,JONES,FORD        7839,7839,7566                  0

ENAME           EMPNO        MGR   LEVELNUM SEQ        ENAMEPATH              EMPNOPATH                  ISLEAF
---------- ---------- ---------- ---------- ---------- ---------------------- ---------------------- ----------
  MILLER         7934       7782          3 1.3.8      KING,CLARK,MILLER      7839,7839,7782                  1
   SMITH         7369       7902          4 1.1.7.1    KING,JONES,FORD,SMITH  7839,7839,7566,7902             1
   ADAMS         7876       7788          4 1.1.4.2    KING,JONES,SCOTT,ADAMS 7839,7839,7566,7788             1

14 rows selected.

SQL> 


SY.

Сообщение было отредактировано: 13 фев 12, 18:36
13 фев 12, 18:28    [12083873]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
andreymx
Member

Откуда: Запорожье
Сообщений: 54377
Андрей Панфилов
Кобанчег,

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

то что прикладуха не умеет оракловые фичи - это плата за поддержку нескольких СУБД
как раз для этого существуют СУБД-независимые компоненты а ля dbTreeView
14 фев 12, 00:53    [12085769]     Ответить | Цитировать Сообщить модератору
 Re: можно ли при помощи MODEL clause построить дерево?  [new]
SY
Member

Откуда: Middlebury, CT USA
Сообщений: 10042
SY,

Actually my sequence caclulations are wrong - it should be PARTITION BY empno in ROW_NUMBER:

WITH StartWith(
               Ename,
               Empno,
               Mgr,
               Seq,
               EnamePath,
               EmpnoPath,
               LevelNum
              ) AS (
                     -- First part of union gets "starting" records
                     SELECT  Ename,
                             Empno,
                             Mgr,
                             TO_CHAR(row_number() over(order by Empno)) As Seq,
                             Ename As EnamePath,
                             TO_CHAR(Empno) As EmpnoPath,
                             1 As LevelNum
                       FROM  EMP
                       WHERE  Mgr IS NULL
                    UNION ALL
                     -- Second part of query "chains" to employees under the manager
                       SELECT  e.Ename,
                               e.Empno,
                               e.Mgr,
                               s.Seq || '.' || row_number() over(partition by e.Mgr order by e.Empno) As Seq,
                               s.EnamePath || ',' || e.Ename As EnamePath,
                               s.EmpnoPath || ',' || s.Empno As EmpnoPath,
                               s.LevelNum + 1 As LevelNum
                         FROM  EMP  e INNER JOIN StartWith s  ON s.Empno = e.Mgr
              )
              SEARCH DEPTH FIRST BY empno SET RowOrder
SELECT  lpad(' ',LevelNum - 1) || Ename Ename,
        Empno,
        Mgr,
        LevelNum,
        Seq,
        EnamePath,
        EmpnoPath,
        CASE
          WHEN LEAD(LevelNum,1,LevelNum) OVER(ORDER BY Seq) <= LevelNum THEN 1
          ELSE 0
        END IsLeaf
  FROM  StartWith
  ORDER BY RowOrder
/

ENAME           EMPNO        MGR   LEVELNUM SEQ        ENAMEPATH              EMPNOPATH                  ISLEAF
---------- ---------- ---------- ---------- ---------- ---------------------- ---------------------- ----------
KING             7839                     1 1          KING                   7839                            0
 JONES           7566       7839          2 1.1        KING,JONES             7839,7839                       0
  SCOTT          7788       7566          3 1.1.1      KING,JONES,SCOTT       7839,7839,7566                  0
   ADAMS         7876       7788          4 1.1.1.1    KING,JONES,SCOTT,ADAMS 7839,7839,7566,7788             1
  FORD           7902       7566          3 1.1.2      KING,JONES,FORD        7839,7839,7566                  0
   SMITH         7369       7902          4 1.1.2.1    KING,JONES,FORD,SMITH  7839,7839,7566,7902             1
 BLAKE           7698       7839          2 1.2        KING,BLAKE             7839,7839                       0
  ALLEN          7499       7698          3 1.2.1      KING,BLAKE,ALLEN       7839,7839,7698                  1
  WARD           7521       7698          3 1.2.2      KING,BLAKE,WARD        7839,7839,7698                  1
  MARTIN         7654       7698          3 1.2.3      KING,BLAKE,MARTIN      7839,7839,7698                  1
  TURNER         7844       7698          3 1.2.4      KING,BLAKE,TURNER      7839,7839,7698                  1

ENAME           EMPNO        MGR   LEVELNUM SEQ        ENAMEPATH              EMPNOPATH                  ISLEAF
---------- ---------- ---------- ---------- ---------- ---------------------- ---------------------- ----------
  JAMES          7900       7698          3 1.2.5      KING,BLAKE,JAMES       7839,7839,7698                  1
 CLARK           7782       7839          2 1.3        KING,CLARK             7839,7839                       0
  MILLER         7934       7782          3 1.3.1      KING,CLARK,MILLER      7839,7839,7782                  1

14 rows selected.

SQL> 


SY.
14 фев 12, 17:55    [12091087]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить