Vu la structure de donnée, l'index doit être sur la table, justement sur (id_projet, seq).
Accessoirement, ça sera plus efficace pour afficher quoi que ce soit, puisque la base de la vue est de faire un ordre par id_projet, seq !
Version imprimable
Pour être barbare... ça l'est !
Que pensez vous de ça :
Je sais, c'est moche mais ça a l'air de répondre à mon besoin.
Est-ce optimisable ?
Résultat :Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 Copier/Coller la définition de TACHE, SELECT P.ID,P.ID_PROJET,P.NOM,P.SEQ,P.ID AS ID_PHASE,NULL AS ID_ACTIVITE,NULL AS ID_TACHE FROM TACHE P WHERE P.NIVEAU = 1 AND P.EST_TACHE = 0 UNION ALL SELECT A.ID,A.ID_PROJET,A.NOM,A.SEQ,MAX(P.ID) KEEP (dense_rank LAST ORDER BY P.SEQ),A.ID,NULL FROM TACHE A INNER JOIN TACHE P ON P.ID_PROJET = A.ID_PROJET AND P.SEQ < A.SEQ AND P.NIVEAU = 1 AND P.EST_TACHE = 0 WHERE A.NIVEAU = 2 AND A.EST_TACHE = 0 GROUP BY A.ID,A.ID_PROJET,A.NOM,A.SEQ UNION SELECT T.ID,T.ID_PROJET,T.NOM,T.SEQ,MAX(P.ID) KEEP (dense_rank LAST ORDER BY P.SEQ),MAX(A.ID) KEEP (dense_rank LAST ORDER BY A.SEQ),T.ID FROM TACHE T LEFT OUTER JOIN TACHE P ON P.ID_PROJET = T.ID_PROJET AND P.SEQ < T.SEQ AND P.NIVEAU = 1 LEFT OUTER JOIN TACHE A ON A.ID_PROJET = T.ID_PROJET AND A.SEQ < T.SEQ AND A.NIVEAU = 2 WHERE T.NIVEAU > 2 GROUP BY T.ID,T.ID_PROJET,T.NOM,T.SEQ UNION SELECT T.ID,T.ID_PROJET,T.NOM,T.SEQ,MAX(P.ID) KEEP (dense_rank LAST ORDER BY P.SEQ),NULL,T.ID FROM TACHE T LEFT OUTER JOIN TACHE P ON P.ID_PROJET = T.ID_PROJET AND P.SEQ < T.SEQ AND P.NIVEAU = 1 WHERE T.NIVEAU = 2 AND T.EST_TACHE = 1 GROUP BY T.ID,T.ID_PROJET,T.NOM,T.SEQ ORDER BY SEQ
http://img802.imageshack.us/img802/6696/image1nv.png
Ça a l'air correct non ?
Hé, j'ai eu une autre idée marrante : utiliser la clause MODEL :)
Ca permet entre autres, à partir du résultat d'un SELECT, de faire joujou comme si tu étais sur Excel.
Un tuto si ça t'intéresse ;)
http://antoun.developpez.com/oracle/...?page=sommaire
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 SELECT * FROM ( SELECT id,id_projet, nom, niveau, seq, est_tache, phase, case when niveau = 2 AND est_tache = 1 then NULL else nullif(max(case niveau when 2 then seq else 0 end) over(partition BY id_projet, phase ORDER BY seq), 0) end activite ,case est_tache when 1 then seq end tache from ( SELECT a.*, max(case niveau when 1 then seq else 0 end) over(partition BY id_projet ORDER BY seq) phase FROM tache a) u ) model dimension by (seq) measures (id, id_projet, nom, niveau, est_tache, phase, activite, tache, 0 phaseid, 0 activiteid, 0 tacheid) rules (phaseid[any] = id[phase[cv()]], activiteid[any] = id[activite[cv()]], tacheid[any] = id[tache[cv()]])
Ah attends, dans la mesure où SEQ n'est sûrement unique que sur un même projet, je pense qu'il faut l'ajouter en dimension :
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13 SELECT * FROM ( SELECT id,id_projet, nom, niveau, seq, est_tache, phase, case when niveau = 2 AND est_tache = 1 then NULL else nullif(max(case niveau when 2 then seq else 0 end) over(partition BY id_projet, phase ORDER BY seq), 0) end activite ,case est_tache when 1 then seq end tache from ( SELECT a.*, max(case niveau when 1 then seq else 0 end) over(partition BY id_projet ORDER BY seq) phase FROM tache a) u ) model dimension by (seq, id_projet) measures (id, nom, niveau, est_tache, phase, activite, tache, 0 phaseid, 0 activiteid, 0 tacheid) rules (phaseid[any, any] = id[phase[cv(), cv()], cv()], activiteid[any, any] = id[activite[cv(), cv()], cv()], tacheid[any, any] = id[tache[cv(), cv()], cv()])
Ce qui me frappe c'est que vos données de départ ressemblent furieusement au résultat d'une requête connect by.
Ici je ne m'intéresse pas au projet qui devrait faire partie de la hiérarchie, mais si c'est à implémenter l'idée reste la même.
Première étape, recréer une vision (id, id_pere) des données.
Puis les extraire avec notre ami connect by, et enfin une petite manipulation de présentation :
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 With SR1 as ( select t1.id, max(t2.id) as id_pere, t1.nom from task t1 left outer join task t2 on t2.niveau = t1.niveau - 1 and t2.sequence < t1.sequence group by t1.id, t1.nom ) , SR2 as ( select connect_by_root id as id_phase , id , nom , level as niveau from SR1 start with id_pere is null connect by prior id = id_pere ) select id_phase , last_value(case when nom like 'Activité%' then id end ignore nulls) over(partition by id_phase order by id asc) as id_activite , case when nom like 'Tache%' then id end as id_tache , nom from SR2 order by id asc; ID_PHASE ID_ACTIVITE ID_TACHE NOM ---------- ----------- ---------- --------------- 1 Phase 1 1 2 Activité 1 1 2 3 Tache 1 1 4 Activité 2 1 4 5 Tache 2 6 Phase 2 6 7 Tache 3 6 8 Activité 3 6 8 9 Tache 4