Bonjour,

J'ai un besoin un peu particulier que je n'arrive pas à traiter sans requête récursive.

J'ai peut être loupé un truc ceci étant dit ...

J'ai donc une table avec 3 dimenssions :
- id_per : l'identifiant d'une personne
- dtDeb : date de début de plage
- dtFin : date de fin de plage.

Dans cette table est loggé l'id d'une personne avec la plage sur laquelle il a travaillé.
On peut remarquer que : dtDeb < dtFin pour une même ligne.
En plus de ceci on a une contrainte fonctionnelle qui spécifie que 2 plages de deux lignes distinct ne peuvent pas se chevaucher.


Le but étant de regrouper les différentes plages selon la personne qui travaille tout en faisant une rupture par différente personne / plage continue de travaille.

Un exemple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
 
donnée en entrée :
idcon    dtDeb    dtFin 
-----------------------------
with tmp as (
select 2, trunc(current_date - interval '10' day), trunc(current_date - interval '9' day) from dual union all
select 2, trunc(current_date - interval '7' day), trunc(current_date - interval '6' day) from dual union all
select 3, trunc(current_date - interval '5' day), trunc(current_date - interval '3' day) from dual union all
select 2, trunc(current_date - interval '2' day), trunc(current_date) from dual union all
select 2, trunc(current_date + interval '2' day), trunc(current_date + interval '4' day) from dual )
 
select * from tmp;

Sortie voulue :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
 
idcon    dtDeb   dtFin
-------------------------------------
2	2013-02-23 	2013-02-27	
3	2013-02-28 	2013-03-02	
2	2013-03-03 	2013-03-09

Ma requête actuelle :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
with tmp as (
select idcon, dtdeb, dtfin, row_number() over(order by dtdeb) as rnk
from tt),
 
rec (idcon, dtdeb, dtfin, rnk, lvl) as (
select idcon, dtdeb, dtfin, rnk, 0 as lvl
from tmp
where rnk = 1
union all
select b.idcon, b.dtdeb, b.dtfin, b.rnk, case when a.idcon = b.idcon then a.lvl else a.lvl + 1 end
from rec a 
inner join tmp b on a.rnk + 1 = b.rnk)
 
select max(idcon), min(dtdeb), max(dtfin), lvl
from rec
group by lvl

Y a-t-il une transformation possible de ceci pour que celà tourne sur une 10g ?

J'ai essayé un peu avec les fonctions de fenêtrages mais n'y suis pas arrivé.

Merci.