IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Oracle Discussion :

Transformer requête recurssive [10g]


Sujet :

SQL Oracle

  1. #1
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut Transformer requête recurssive
    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.

  2. #2
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 947
    Points : 5 846
    Points
    5 846
    Par défaut
    Si le numéro du level n'a pas d'importance, on peut faire comme ça pour regrouper :
    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
    18
    19
    20
    21
    22
    23
    24
    SQL> WITH tt AS (
      2  SELECT 2 idcon, trunc(current_date - interval '10' day) dtdeb, trunc(current_date - interval '9' day) dtfin FROM dual union ALL
      3  SELECT 2, trunc(current_date - interval '7' day), trunc(current_date - interval '6' day) FROM dual union ALL
      4  SELECT 3, trunc(current_date - interval '5' day), trunc(current_date - interval '3' day) FROM dual union ALL
      5  SELECT 2, trunc(current_date - interval '2' day), trunc(current_date) FROM dual union ALL
      6  SELECT 2, trunc(current_date + interval '2' day), trunc(current_date + interval '4' day) FROM dual
      7  ),
      8     tmp AS (
      9  SELECT idcon, dtdeb, dtfin,
     10         row_number() over(ORDER BY dtdeb) AS rnk,
     11         row_number() over (partition by idcon order by dtdeb) as rk
     12    FROM tt
     13  )
     14  SELECT max(idcon), min(dtdeb), max(dtfin), rnk-rk as lvl
     15    FROM tmp
     16   GROUP BY rnk-rk;
     
    MAX(IDCON) MIN(DTDE MAX(DTFI        LVL
    ---------- -------- -------- ----------
             2 03/03/13 09/03/13          1
             3 28/02/13 02/03/13          2
             2 23/02/13 27/02/13          0
     
    SQL>
    Regarde ce post s'il y a besoin d'affiner avec first/last :
    http://www.developpez.net/forums/d13...-dintervalles/

  3. #3
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Points : 5 345
    Points
    5 345
    Par défaut
    Merci pour la piste.

    En changeant un peu les données en entrées (cas auquel je n'avais pas pensé) ca ne va pas marcher par contre :
    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
     
    with rr as (
    select 2 as idcon, trunc(current_date - interval '10' day) as dtdeb, trunc(current_date - interval '9' day) as dtfin from dual union all
    select 3, trunc(current_date - interval '8' day), trunc(current_date - interval '7' day) from dual union all
    select 2, trunc(current_date - interval '5' day), trunc(current_date - interval '4' day) from dual),
     
    tmp as (
    select idcon, dtdeb, dtfin, 
    row_number() over(order by dtdeb) as rnk, 
    row_number() over(partition by idcon order by dtdeb) as lvl
    from rr)
     
     
    select idcon, dtdeb, dtfin, rnk, lvl, rnk - lvl
     from tmp

    Je vais regardez d'un peu plus prés la proposition de Waldar, pour voir si je peux arriver à quelque chose.


    Edit : en changeant le group by ca devrait le faire.

    Merci.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Transformer requête sélection en requête suppression en VBA
    Par P'tit aviateur dans le forum Requêtes et SQL.
    Réponses: 10
    Dernier message: 13/03/2009, 15h34
  2. [CR10] Transformation requête SQL
    Par jfphan dans le forum SAP Crystal Reports
    Réponses: 5
    Dernier message: 04/04/2008, 10h57
  3. Transformation requête imbriquée en requête simple
    Par pbatty1 dans le forum Requêtes
    Réponses: 3
    Dernier message: 12/11/2007, 15h42
  4. transformation requête en table
    Par By-nôm dans le forum Requêtes et SQL.
    Réponses: 10
    Dernier message: 09/08/2006, 10h44
  5. Transformer requête imbriquée en jointure
    Par Nadoo dans le forum Requêtes
    Réponses: 4
    Dernier message: 07/05/2006, 00h41

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo