Oracle requête hiérarchique: comment inclure parent haut niveau
-
23-08-2019 - |
Question
J'ai une requête hiérarchique pour suivre une structure hiérarchique. Cela fonctionne presque, sauf que ce n'est pas le nœud de rapports de niveau très haut, probablement parce que les gens de haut niveau « rapport » eux-mêmes.
La requête est:
select
level,
empid,
parentid
from usertable
connect by nocycle prior parentid= empid
start with empid = 50
produit:
LEVEL EMPID PARENTID
------ ----- --------
1 50 258
2 258 9555
3 9555 17839
Je ne reçois pas un niveau 4, car il ressemblerait à ceci:
4 17839 17839
Sans modifier les données, est-il un moyen de modifier ma requête afin que tous les 4 niveaux sont retournés? Le but est d'obtenir les empids, donc je peux faire un chèque pour
id in (hierarchical subquery)
BTW, si je retire la nocycle de la requête que je reçois une erreur.
La solution
Chris,
Vous obtenez seulement 3 rangs parce que votre ligne de haut niveau n'est pas réglé comme il se doit pour traiter les requêtes hiérarchiques. En règle générale la ligne de haut niveau, ou KING président dans la table EMP bien connue d'Oracle, n'a pas gestionnaire. Dans votre cas, vous ne devez pas définir la parentid de 17389-17389 lui-même, mais à NULL. Soit mettre à jour le tableau en conséquence, ou en vue d'accueillir cette situation.
Un exemple:
SQL> select empno
2 , mgr
3 from emp
4 where empno in (7876,7788,7566,7839)
5 /
EMPNO MGR
---------- ----------
7566 7839
7788 7566
7839 7839
7876 7788
4 rijen zijn geselecteerd.
Cette partie de la table EMP a quatre niveaux avec sa ligne de premier niveau (7839) fixé à lui-même. La même chose que votre empid 17839. Et cela conduit à trois lignes à l'aide de votre requête:
SQL> select level
2 , empno
3 , mgr
4 from emp
5 connect by nocycle prior mgr = empno
6 start with empno = 7876
7 /
LEVEL EMPNO MGR
---------- ---------- ----------
1 7876 7788
2 7788 7566
3 7566 7839
3 rijen zijn geselecteerd.
Soit utiliser un (inline) en vue de fixer la colonne mgr / parentid null pour le niveau haut:
SQL> select level
2 , empno
3 , mgr
4 from ( select empno
5 , nullif(mgr,empno) mgr
6 from emp
7 )
8 connect by nocycle prior mgr = empno
9 start with empno = 7876
10 /
LEVEL EMPNO MGR
---------- ---------- ----------
1 7876 7788
2 7788 7566
3 7566 7839
4 7839
4 rijen zijn geselecteerd.
Ou fixer vos données avec une instruction UPDATE:
SQL> update emp
2 set mgr = null
3 where empno = 7839
4 /
1 rij is bijgewerkt.
SQL> select level
2 , empno
3 , mgr
4 from emp
5 connect by nocycle prior mgr = empno
6 start with empno = 7876
7 /
LEVEL EMPNO MGR
---------- ---------- ----------
1 7876 7788
2 7788 7566
3 7566 7839
4 7839
4 rijen zijn geselecteerd.
Et vous pouvez laisser le mot-clé NOCYCLE aussi bien, après avoir terminé la fixation.
Cordialement, Rob.
Autres conseils
Vous devez faire la hiérarchie dans l'autre sens, de la racine aux feuilles.
select
level,
empid,
parentid
from usertable
start with empid = 17839
connect by empid != 17839 and prior empid = parentid
LEVEL EMPID PARENTID
---------------------- ---------------------- ----------------------
1 17839 17839
2 9555 17839
3 258 9555
4 50 258
4 rows selected
Vous ne devez pas changer votre structure.
il suffit d'utiliser la requête suivante
select
level,
empid,
parentid
from usertable
connect by prior parentid = empid
AND parentid <> empid -- This line prohibits cycling and ALLOWS a row where parentid = empid
start with empid = 50
La réponse de Van Heddegem Roeland ne fonctionne pas pour moi, je l'avais déjà essayé, mais je l'ai réussi à le faire sans une vue en ligne, dans la clause de connexion, en ajoutant: -
and prior empid <> parentid
Le message suivant explique pourquoi cela fonctionne - si vous pouvez obtenir votre tête autour d'elle! Bien qu'il ne fait son sens logique une fois que vous ne l'obtenez « ». (Il est à voir avec l'ordre d'évaluation de chaque côté de l'opérateur <>).
Oracle: Se connecter par boucle dans les données utilisateur
La vue en ligne fonctionne, mais sans la recherche sur votre ensemble de données particulier, je ne sais pas quel impact une vue en ligne pourrait avoir sur le chemin de la requête. L'ajout de la clause supplémentaire est probablement la façon « correcte » de le faire dans la plupart des situations, à mon humble avis.
semble que vous avez un cycle dans les données. Sans « nocycle » ça ne marchera pas tout de suite. Si vous savez que toutes vos données niveau d'imbrication maximum de 4, alors vous pouvez ajouter la condition « et le niveau <= 4 » et retirez nocycle. Si le travail.