2010-01-26 9 views
3

J'ai une requête hiérarchique dans Oracle 10 SQL qui fonctionnait auparavant. Cependant, j'ai enlevé la vue matérialisée sur laquelle elle était basée, et maintenant je ne peux pas la faire sortir correctement, même en laissant cette vue complètement.Requête hiérarchique dans Oracle - hors de contrôle?

La requête originale ressemblait à ceci:

select oh.name, oh.description 
    , sys_connect_by_path(groupname, ':') "Groups" 
    , (select count(*) 
     from ml.lastobsmv 
     where lastobsmv.hdid = oh.hdid) as obscount 
from ml.obshead oh 
    join ml.hiergrps hg on oh.groupid = hg.groupid 
    connect by prior hg.groupid = hg.parentid 

Je présume que cela fonctionne encore, mais sans la vue lastobsmv, je ne peux pas tester.

Si je le couper jusqu'à

select oh.name, oh.description 
from ml.obshead oh 
    join ml.hiergrps hg on oh.groupid = hg.groupid 

il fonctionne toujours, le retour 41K records. Cependant, lorsque j'utilise la clause connect by, elle devient incontrôlable et renvoie des millions d'enregistrements (je dois généralement l'annuler avant d'obtenir un compte précis).

select oh.name, oh.description 
    , sys_connect_by_path(groupname, ':') "Groups" 
from ml.obshead oh 
    join ml.hiergrps hg on oh.groupid = hg.groupid 
    connect by prior hg.groupid = hg.parentid 

Suis-je manque quelque chose de vraiment flagrant ici, ou je comprends mal la façon dont cela est censé fonctionner? Merci. .


Vadim,

Il doit retourner une liste des termes d'observation ainsi que le groupe auquel ils sont dans, par exemple,

Obshead:

# CYCLE DAYS, number of days in menstrual cycle, 100 

HierGrps:

100, 50, Gynecology 
50, 10, Tx 
10, 0, Basic 

devrait produire

# CYCLE DAYS, number of days in menstrual cycle, :Basic:Tx:Gynecology 

(éventuellement avec le nombre de fois que ce terme obs a été utilisé, mais je vais inquiéter à ce sujet plus tard).

+1

Une perspective, s'il vous plaît. Nous aimerions tous aider si nous pouvions seulement comprendre ce que vous vouliez faire. –

+0

Pourriez-vous poster une description de la table obshead et quelques exemples de données ainsi qu'une description de la table hiergrps et un peu plus de données d'échantillon? –

+0

@SarekOfVulcan: Je ne choisis pas Peter Lang ici, mais pourquoi avez-vous accepté sa réponse? Non seulement il produit la colonne 'Group' dans l'ordre inverse, mais il produit également une ligne supplémentaire lorsqu'il est exécuté sur les données d'exemple dans ma solution. –

Répondre

3
select 
    oh.name, 
    oh.description, 
    hg."Groups" 
from 
    obshead oh 
    join (select 
       groupid, 
       sys_connect_by_path(groupname, ':') "Groups" 
      from 
       hiergrps 
      start with 
       parentid = 0 
      connect by 
       prior groupid = parentid 
     ) hg 
     on oh.groupid = hg.groupid 

est ici les données d'exemple que je l'ai utilisé pour tester la requête:

create table obshead 
(name varchar2(30) 
, description varchar2(30) 
, groupid number(3) 
); 
insert into obshead (name, description, groupid) 
    select 'Name One', 'Description One', 100 from dual union all 
    select 'Name Two', 'Description Two', 200 from dual 
; 

create table hiergrps 
(groupid number(3) 
, parentid number(3) 
, groupname varchar2(30) 
); 
insert into hiergrps (groupid, parentid, groupname) 
    select 100, 50, 'Gynecology' from dual union all 
    select 50, 10, 'Tx'   from dual union all 
    select 10, 0, 'Basic'  from dual 
; 
+0

Ah, 'commence par parentid = 0'. J'aime ça, cela me sauverait la récupération du niveau maximum. –

+0

+1: Je n'étais pas au courant du fait que toutes les entrées sont des enfants de base –

2

Je ne suis pas sûr de savoir comment votre requête initiale pourrait fonctionner, mais c'est la meilleure solution que je suis arrivé à travailler ...

Il retourne Gynecology:Tx:Basic bien (ordre inverse).

SELECT 
    oh.name, 
    oh.description, 
    (SELECT SYS_CONNECT_BY_PATH(groupname, ':') 
    FROM hiergrps hg 
    WHERE CONNECT_BY_ISLEAF = 1 
     START WITH hg.groupid = oh.groupid 
     CONNECT BY PRIOR hg.parentid = hg.groupid 
) "groups" 
FROM obshead oh 

avez-vous utilisé vraiment prior hg.groupid = hg.parentid et non prior hg.parentid = hg.groupid?
Je peux être interpréter mal vos données de test, mais il semble que je dois commencer par groupid=100, parentid=50 et puis obtenir groupid=50 parentid=10?

+0

Je ne ai vraiment utiliser groupe avant = parent, parce que ce à quoi il ressemblait dans la documentation: SELECT last_name "employé", CONNECT_BY_ISLEAF "IsLeaf", LEVEL, SYS_CONNECT_BY_PATH (last_name, '/') "Path" FROM employees WHERE LEVEL <= 3 ET department_id = 80 COMMENCER PAR employee_id = 100 CONNEXION PAR AVANT employee_id = ID_gestionnaire ET NIVEAU <= 4; – SarekOfVulcan

1

Pierre ressemble plus élégant, mais voici ce que je suis venu avec compte tenu des hypothèses suivantes sur les tables et les données:

create table obshead 
(
cycledays number, 
numdaysincycle number, 
groupid number 
); 

create table hiergrps 
(
groupid number, 
parent number, 
groupname varchar2(40) 
); 


insert into obshead select 100 cycledays, 30 numdaysincycle, 100 groupid from dual; 
insert into hiergrps select 100 groupid, 50 parent, 'Gyncecology' groupname from dual; 
insert into hiergrps select 50 groupid, 10 parent, 'Tx' groupname from dual; 
insert into hiergrps select 10 groupid, 0 parent, 'Basic' groupname from dual; 

select cycledays, 
     numdaysincycle, 
     groups 
    from (select groupid, 
       parent, 
       sys_connect_by_path(groupname, ':') groups 
      from hiergrps hg 
     start with parent = 0 
     connect by prior hg.groupid = hg.parent 
     ) hg, 
     obshead obs 
where obs.groupid = hg.groupid; 

Ce qui revient pour moi:

100 30 :Basic:Tx:Gyncecology 

Modifier: Mis à jour le produit Vadim incorporer de parentid = 0

2

il semble que le REJOIGNEZ est évaluée avant la connecter par, de sorte que votre une ligne ne peut pas construire la hiérarchie. Avec une sous-requête, vous obtiendrez ce que vous voulez:

SQL> SELECT oh.NAME, oh.description, 
    2   MAX(groups) keep(dense_rank LAST ORDER BY lvl) groups 
    3 FROM obshead oh 
    4 JOIN (SELECT sys_connect_by_path(groupname, ':') Groups, 
    5     hg.groupid, hg.parentid, LEVEL lvl 
    6   FROM hiergrps hg 
    7   CONNECT BY PRIOR hg.groupid = hg.parentid) hg 
    8  ON oh.groupid = hg.groupid 
    9 GROUP BY oh.NAME, oh.description; 

NAME   DESCRIPTION      GROUPS 
------------ --------------------------------- --------------------------- 
# CYCLE DAYS number of days in menstrual cycle :Basic:Tx:Gynecology 
+0

Je reçois un ORA-00937: pas une erreur de fonction de groupe d'un seul groupe de cela. Si je laisse tomber la ligne Max (groupes), cela fonctionne bien, mais ce genre de défaites le but. :-) – SarekOfVulcan

+0

@Sarek: Je l'ai testé avec 11gr1. J'ai ajouté une clause GROUP BY, cela devrait fonctionner avec 10g –

+0

Yup, l'a réparé. Merci! Maintenant, pour savoir lequel a le meilleur profil de requête ... – SarekOfVulcan