Professional Documents
Culture Documents
Relação pai-filho
na mesma tabela.
Enviado por Cesar Inacio Martins em ter, 29/09/2009 - 17:02
http://www.imartins.com.br/informix/artigos/utilizando-selects-hierarquicos-
relacao-pai-filho-mesma-tabela
Este recurso foi incluído na versão 11.50 xC5, com uma nova sintaxe o comando
SELECT permite uma escrita fácil para este tipo de relacionamento, e para
hierarquia superior.
permite que você filtre ou exiba dados da hierarquia de modo muito fácil e
Sintaxe e comandos
A sintaxe básica é:
[, SYS_CONNECT_BY_PATH()] [, LEVEL]
FROM ...
WHERE ...
START WITH: Define qual registro será o inicio da busca pela hierarquia.
Este parâmetro não é obrigatório mas muito útil. Se você não informa-lo
o select irá processar a hierarquia de todos os registros encontrados.
PRIOR: Utilizado apenas na clausula CONNECT BY, faz o relacionamento
entre os níveis.
Deve-se informar este operador sempre antes de um campo que seja do
nível anterior (superior, do ponto de vista do select). Pode utilizar o
operador mais de uma vez para fazer filtros.
NOCYCLE: Pode ocorrer situações onde o relacionamento gere um loop o que
poderia gerar um SELECT infinito. O banco detecta estas situações e gera
o erro -26079 quando ocorre. Para evitar este erro deve-se utilizar este
operador e então o retorno do select irá finalizar automaticamente no
ultimo item antes de reiniciar o loop.
LEVEL: Exibe o nível do registro dentro da hierarquia, baseado na
hierarquia retornada pelo select.
Este operador também pode ser utilizado na clausula CONNECT para
filtros.
CONNECT_BY_ISLEAF: Retorna 1 (numero um) se o registro é um leaf, ou
seja, se é o ultimo registro da hierarquia e não possui filhos.
Este comando não pode ser utilizado em nenhuma clausula de condição
(where, connect, start).
CONNECT_BY_ISCYCLE: Pode ser utilizado apenas quando o operador NOCYCLE
foi especificado. Retorna 1 (numero um) quando o registro é o ultimo da
hierarquia e possui o relacionamento que irá iniciar o loop. Este
comando não pode ser utilizado em nenhuma clausula de condição (where,
connect, start).
CONNECT_BY_ROOT [campo]: Exibe um campo do registro pai/root na
hierarquia do registro exibido. Este comando não pode ser utilizado em
nenhuma clausula de condição (where, connect, start).
SYS_CONNECT_BY_PATH(campo, separador): Retorna uma string
(LVARCHAR(4000)) com o path de toda hierarquia utilizado o campo e
separador especificado. Este comando não pode ser utilizado em nenhuma
clausula de condição (where, connect, start).
ORDER SIBLINGS BY: Este operador só pode ser utilizado com o CONNECT BY.
Ele reordena apenas os itens que fazem parte do do mesmo nível na
hierarquia.
Clasula WHERE
The clauses of a SELECT statement that includes the Hierarchical clause are
processed in the following sequence:
1. FROM clause (for only a single table object in the current database)
2. Hierarchical clause
3. WHERE clause (without join predicates)
4. GROUP BY clause
5. HAVING clause
6. Projection clause
7. ORDER BY clause
Exemplos
cd_emp int
, desc varchar(16)
, cd_emp_pai int );
Table created.
Table altered.
# até a matriz
12 Posto_Avancado 4 P 11
11 Filial_RJ2 F 9
9 QG_RJ QG 1
1 Matriz M
4 row(s) retrieved.
1 Matriz M
9 QG_RJ QG 1
11 Filial_RJ2 F 9
12 Posto_Avancado 4 P 11
10 Filial_RJ1 F 9
2 QG_SP QG 1
5 Filial_SP3 F 2
4 Filial_SP2 F 2
8 Posto_Avancado 3 P 4
3 Filial_SP1 F 2
7 Posto_Avancado 2 P 3
6 Posto_Avancado 1 P 3
12 row(s) retrieved.
1 row(s) updated.
12 Posto_Avancado 4 P 11
11 Filial_RJ2 F 9
9 QG_RJ QG 1
Error in line 39
SELECT *
, CONNECT_BY_ISCYCLE
FROM empresas
12 Posto_Avancado 4 P 11 0
11 Filial_RJ2 F 9 0
9 QG_RJ QG 1 0
1 Matriz M 12 1
4 row(s) retrieved.
# Desfaço o loop
1 row(s) updated.
FROM empresas
START WITH cd_emp = 6
6 Posto_Avancado 1 P 3 0 1
3 Filial_SP1 F 2 0 2
2 QG_SP QG 1 0 3
1 Matriz M 1 4
4 row(s) retrieved.
FROM empresas
1 Matriz M 0 1
9 QG_RJ QG 1 0 2
11 Filial_RJ2 F 9 0 3
12 Posto_Avancado 4 P 11 1 4
10 Filial_RJ1 F 9 1 3
2 QG_SP QG 1 0 2
5 Filial_SP3 F 2 1 3
4 Filial_SP2 F 2 0 3
8 Posto_Avancado 3 P 4 1 4
3 Filial_SP1 F 2 0 3
7 Posto_Avancado 2 P 3 1 4
6 Posto_Avancado 1 P 3 1 4
12 row(s) retrieved.
# Aqui podemos ver a utilização do operador LEVEL na
FROM empresas
1 Matriz M 0 1
9 QG_RJ QG 1 0 2
11 Filial_RJ2 F 9 1 3
10 Filial_RJ1 F 9 1 3
2 QG_SP QG 1 0 2
5 Filial_SP3 F 2 1 3
4 Filial_SP2 F 2 1 3
3 Filial_SP1 F 2 1 3
8 row(s) retrieved.
SELECT *
, LEVEL
FROM empresas
11 Filial_RJ2 F 9 Filial_RJ2
1
12 Posto_Avancado 4 P 11 Filial_RJ2
2
10 Filial_RJ1 F 9 Filial_RJ1
1
5 Filial_SP3 F 2 Filial_SP3
1
4 Filial_SP2 F 2 Filial_SP2
1
8 Posto_Avancado 3 P 4 Filial_SP2
2
3 Filial_SP1 F 2 Filial_SP1
1
7 Posto_Avancado 2 P 3 Filial_SP1
2
6 Posto_Avancado 1 P 3 Filial_SP1
2
9 row(s) retrieved.
FROM empresas
1 Matriz M /Matriz
9 QG_RJ QG /Matriz/QG_RJ
11 Filial_RJ2 F /Matriz/QG_RJ/Filial_RJ2
12 Posto_Avancado 4 P
/Matriz/QG_RJ/Filial_RJ2/Posto_Avancado 4
10 Filial_RJ1 F /Matriz/QG_RJ/Filial_RJ1
2 QG_SP QG /Matriz/QG_SP
5 Filial_SP3 F /Matriz/QG_SP/Filial_SP3
4 Filial_SP2 F /Matriz/QG_SP/Filial_SP2
8 Posto_Avancado 3 P
/Matriz/QG_SP/Filial_SP2/Posto_Avancado 3
3 Filial_SP1 F /Matriz/QG_SP/Filial_SP1
7 Posto_Avancado 2 P
/Matriz/QG_SP/Filial_SP1/Posto_Avancado 2
6 Posto_Avancado 1 P
/Matriz/QG_SP/Filial_SP1/Posto_Avancado 1
12 row(s) retrieved.
# e WHERE
SELECT *, LEVEL
FROM empresas
1 Matriz M 1
9 QG_RJ QG 1 2
11 Filial_RJ2 F 9 3
10 Filial_RJ1 F 9 3
2 QG_SP QG 1 2
5 Filial_SP3 F 2 3
4 Filial_SP2 F 2 3
3 Filial_SP1 F 2 3
8 row(s) retrieved.
SELECT *, LEVEL
FROM empresas
WHERE LEVEL != 2
1 Matriz M 1
11 Filial_RJ2 F 9 3
10 Filial_RJ1 F 9 3
5 Filial_SP3 F 2 3
4 Filial_SP2 F 2 3
3 Filial_SP1 F 2 3
6 row(s) retrieved.
SELECT *, LEVEL
FROM empresas
1 Matriz M 1
9 QG_RJ QG 1 2
11 Filial_RJ2 F 9 3
10 Filial_RJ1 F 9 3
2 QG_SP QG 1 2
5 Filial_SP3 F 2 3
4 Filial_SP2 F 2 3
3 Filial_SP1 F 2 3
8 row(s) retrieved.
SELECT *, LEVEL
FROM empresas
1 Matriz M 1
9 QG_RJ QG 1 2
10 Filial_RJ1 F 9 3
11 Filial_RJ2 F 9 3
12 Posto_Avancado 4 P 11 4
2 QG_SP QG 1 2
3 Filial_SP1 F 2 3
6 Posto_Avancado 1 P 3 4
7 Posto_Avancado 2 P 3 4
4 Filial_SP2 F 2 3
8 Posto_Avancado 3 P 4 4
5 Filial_SP3 F 2 3
12 row(s) retrieved.
Database closed.
Debugando
Para identificar como um select hierarquico está sendo utilizado, utilize o
comando SET EXPLAIN, através deste comando é possível ver e entender como o
Informix faz os relacionamentos internamente e aplica os filtros.
Exemplo de um output do SET EXPLAIN:
------
SELECT *
, LEVEL
FROM empresas
---------------------------
x0(cd_emp,desc,tipo,cd_emp_pai,dtab_22679_439_p_cd_emp,level,connect_b
y_isleaf,dtab_22679_439_stkcol
Subquery:
---------
Estimated Cost: 8
Subquery:
---------
Estimated Cost: 5
Query statistics:
-----------------
Table map :
----------------------------
----------------------------
t1 dtab_22679_439
-----------------------------------
clscan t1 9 00:00.00
Média:
.9
Média: 4.9 (10 votos)
Cancelar a avaliação
Sua avaliação:
ancelar a avaliação
oor
kay
om
reat
wesome
Sua avaliação: Nenhum
32384 leituras
Tags:
sql
responder
Possibilidade de solução
Enviado por Cesar Inacio Martins em ter, 18/09/2012 - 08:42.
Odie,
O jeito mais "facil" que vi para a solução é trabalhar com o "START WITH" , porém o nivel
que vc quer realizar o sum, vc precisa pegar antecipadamente, via tabela temporária ou
especificando no select :
Resultado final :
Matriz 1 M 3 1
QG_RJ 9 QG 1 10 2
Filial 11 F 9 3 3
Post 12 P 11 4 4
Filial 10 F 9 11 3
QG_SP 2 QG 1 4 2
Filial 5 F 2 1 3
Filial 4 F 2 2 3
Post 8 P 4 1 4
Filial 3 F 2 1 3
Post 7 P 3 2 4
Post 6 P 3 3 4
desc valor
QG_RJ 28
QG_SP 14
desc valor
QG_RJ 28
QG_SP 14
where level = 2
FROM empresas
group by 1
FROM empresas
group by 1