2017-10-09 6 views
0


J'ai les données ci-dessous qui représente une hiérarchie d'employés, et j'ai besoin d'identifier toutes les permutations possibles de l'employé/superviseur. J'ai jeté un coup d'œil à l'oracle Tree Walk qui semble devoir faire l'affaire, mais je n'arrive pas à le faire fonctionner. Le problème est que je dois lister une ligne pour chaque combinaison de gestionnaire/employé, ceci inclut le gestionnaire de gestionnaire etc. (J'ai édité pour ajouter dans des noms à la question)Oracle Hierarchical Query - informations étendues requises

Est-ce que quelqu'un a des idées comment ceci pourrait être fait ?

DONNÉES

SUPER SUP_NAME  EMP EMP_NAME 
^^^^^ ^^^^^^^   ^^^ ^^^^^^^ 
1  Big Boss   100 Sub Boss 
100 Sub Boss   200 Field Boss 
200 Field Boss  300 Field Emp 

RESULTAT SOUHAITE

SUPER EMP SUP_NAME  EMP_NAME 
^^^^^ ^^^ ^^^^^^^^  ^^^^^^^^ 
1  100 Big Boss  Sub Boss 
1  200 Big Boss  Field Boss 
1  300 Big Boss  Field Emp 
100  200 Sub Boss  Field Boss 
100  300 Sub Boss  Field Emp 
200  300 Field Boss Field Emp 
300   Field Emp 
+1

Quelle requête avez-vous essayé jusqu'à présent techGuy ..? –

+0

J'ai essayé celui de 'Ponder Stibbons' (union) il y a peu de temps, et ça a fonctionné parfaitement, même si je ne pouvais pas trouver la bonne façon d'ajouter les noms, donc j'ai édité la question originale pour demander comment tirer les noms à travers. – TechGuy

+0

Maintenant mis à jour la réponse par @ponderstibbons pour inclure les colonnes révisées de supername, empname qui fonctionne, voir la première réponse – TechGuy

Répondre

2

Utilisation connect_by_root dans la requête hiérarchique standard et ajouter des employés qui ne sont pas responsables en utilisant union et minus:

select connect_by_root(super) super, emp from data connect by super = prior emp 
union 
select emp, null from data minus select super, null from data 

Test:

with data (super, emp) as (
    select 1, 100 from dual union all 
    select 100, 200 from dual union all 
    select 200, 300 from dual) 
select connect_by_root(super) super, emp from data connect by super = prior emp 
union 
select emp, null from data minus select super, null from data 

Résultat:

 SUPER  EMP 
---------- ---------- 
     1  100 
     1  200 
     1  300 
     100  200 
     100  300 
     200  300 
     300 
7 rows selected 
+0

Bonne réponse! Deux suggestions cependant: (1) Utilisez UNION ALL - il n'y a aucune raison pour l'UNION beaucoup moins efficace; (2) utiliser une clause NOT IN (une anti-jointure), au lieu de l'opération MINUS beaucoup moins efficace. – mathguy

+0

Votre solution a fonctionné comme un charme, j'ai utilisé l'un 'Union', alors merci pour votre aide. J'essayais d'ajouter le nom du superviseur et le nom Emp, mais je n'arrive pas à le faire fonctionner correctement, comment puis-je les ajouter dans la requête Union? – TechGuy

+0

@ponderstibbons - Mise à jour vous répondez à ajouter dans les autres colonnes que j'ai ajoutées à la requête originale. – TechGuy

0

Essayez cette requête. Notez que vous aurez besoin d'une ligne avec 300, NULL pour inclure 300, NULL dans le jeu de résultats.

WITH yourtable (super, emp) 
    AS (SELECT 1, 
       100 
     FROM dual 
     UNION ALL 
     SELECT 100, 
       200 
     FROM dual 
     UNION ALL 
     SELECT 200, 
       300 
     FROM dual 
     UNION ALL 
     SELECT 300, 
       NULL 
     FROM dual), 
    datatable 
    AS (SELECT super, 
       Ltrim(Sys_connect_by_path(emp, ','), ',') path 
     FROM yourtable 
     START WITH emp IS NULL 
     CONNECT BY PRIOR super = emp) 
SELECT DISTINCT super, 
       Regexp_substr(path, '[^,]+', 1, LEVEL) AS data 
FROM datatable 
CONNECT BY Regexp_substr(path, '[^,]+', 1, LEVEL) IS NOT NULL 
ORDER BY super; 
+0

Peut-être que cela fonctionnera, mais il est très inefficace. Utilisez plutôt des fonctions de requête hiérarchiques standard, comme l'a montré @ponderstibbons. – mathguy

+0

@mathguy: Oui. n'a pas réalisé à propos de 'connect_by_root (super)' –