Программирование >>  Преобразование значений null 

1 ... 168 169 170 [ 171 ] 172 173 174 ... 219


when 2 then branch

else leaf

end as JONES SUBORDINATES

from

select

a.ename as root,

b.ename as branch,

c.ename as leaf

from

emp a, emp b, emp c

where

a.ename = JONES

a.empno = b.mgr

b.empno = c.mgr

) x,

t100

where

t100.id <= b

В качестве альтернативы можно использовать представления и объединять (UNION) результаты. Если созданы следующие представления:

create view v1 as

select ename,mgr,empno

from emp where ename = JONES

create view v2 as

select ename,mgr,empno from emp

where mgr = (select empno from v1)

create view v3 as

select ename,mgr,empno from emp

where mgr in (select empno from v2)

решение будет таким:

select ename from v1 union

select ename from v2 union

select ename from v3

Обсуждение

DB2 и SQL Server

Рекурсивный оператор WITH упрощает решение этой задачи. Первая часть оператора WITH, верхняя часть UNION ALL возвращает строку служащего JONES. Необходимо получить ENAME, чтобы увидеть имя, и EMPNO, чтобы использовать его для объединения. Нижняя часть UNION ALL рекурсивно объединяет EMP.MGR с X.EMPNO. Ус-



ловие объединения будет применяться до тех пор, пока не будет исчерпано результирующее множество.

Oracle

Оператор START WITH указывает запросу сделать JONES корневым узлом. Условие в операторе CONNECT BY управляет обходом дерева, который будет продолжаться до тех пор, пока условие истинно.

PostgreSQL и MySQL

Техника, используемая здесь, аналогична применяемой во втором рецепте данной главы, Представление отношений потомок-родитель-прародитель . Основной недостаток в том, что заранее должна быть известна глубина иерархии.

Определение узлов: ветвления, концевого, корневого

Задача

Требуется определить, узлом какого типа является данная строка: концевым узлом, узлом ветвления или корневым узлом. В данном примере концевым узлом считается служащий, не являющийся руководителем. Узел ветвления - это служащий, являющийся как руководителем, так и подчиненным. Корневой узел - служащий, не имеющий руководителя. Для отражения статуса каждой строки в иерархии используется 1 (TRUE) или 0 (FALSE). Должно быть получено следующее результирующее множество:

ENAME IS LEAF IS BRANCH IS ROOT

KING 0 0 1

JONES 0 1 0

SCOTT 0 1 0

FORD 0 1 0

CLARK 0 1 0

BLAKE 0 1 0

ADAMS 1 0 0

MILLER 1 0 0

JAMES 1 0 0

TURNER 1 0 0

ALLEN 1 0 0

WARD 1 0 0

MARTIN 1 0 0

SMITH 1 0 0

Решение

Важно понимать, что таблица EMP смоделирована как древовидная иерархия, не рекурсивная, значение поля MGR корневых узлов - NULL. Если бы в EMP использовалась рекурсивная структура данных, корне-



вые узлы были бы автореферентными (т. е. ссылались бы сами на себя, и значением поля MGR для служащего KING было бы значение поля EMPNO этого же самого KING). Автореферентность показалась мне лишенной здравого смысла, и поэтому в поле MGR корневых узлов я поместил значение NULL. Значительно упростят работу с древовидными иерархиями и сделают их потенциально более эффективными, чем рекурсивные иерархии, операторы CONNECT BY для пользователей Oracle и WITH для пользователей DB2/SQL Server. Применяя CONNECT

BY или WITH при работе с рекурсивной иерархией, будьте начеку: все может закончиться циклом. Чтобы этого не произошло, в коде должны быть предприняты соответствующие меры предосторожности.

DB2, PostgreSQL, MySQL и SQL Server

Чтобы верно определить один из трех типов узлов и возвратить соответствующее логическое значение (1 или 0), используйте три скалярных подзапроса:

1 select e.ename,

2 (select sign(count(*)) from emp d

3 where 0 =

4 (select count(*) from emp f

5 where f.mgr = e.empno)) as is leaf, b (select sign(count(*)) from emp d

7 where d.mgr = e.empno

8 and e.mgr is not null) as is branch,

9 (select sign(count(*)) from emp d

10 where d.empno = e.empno

11 and d.mgr is null) as is root

12 from emp e

13 order by 4 desc,3 desc

Oracle

Решение с применением скалярных подзапросов подойдет и для Oracle и должно использоваться для версий до Oracle Database lOg. Следующее решение для идентификации корневых и концевых узлов опирается на предлагаемые Oracle встроенные функции (которые были введены в Oracle Database lOg). Это функции CONNECT BY ROOT и CON-NECT BY ISLEAF соответственно:

I select ename,

2 connect by isleaf is leaf,

3 (select count(*) from emp e

4 where e.mgr = emp.empno

5 and emp.mgr is not null

b and rownum = 1) is branch,

7 decode(ename,connect by root(ename),1,0) is root

8 from emp

9 start with mgr is null

10 connect by prior empno = mgr

II order by 4 desc, 3 desc



1 ... 168 169 170 [ 171 ] 172 173 174 ... 219

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика