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

PL/SQL Oracle Discussion :

PL/SQL Regroupement de date


Sujet :

PL/SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 39
    Par défaut PL/SQL Regroupement de date
    Bonjour,

    Je travaille sur une table POSTE[Id, nom, dateDebut, DateFin] et une table SITUATION[Id, dateDebSit,DateFinSit, id_Poste]
    J'ai 2 paramètres Début et Fin et je dois recuperer pour chaque poste les intervalles de dates ou le poste sera inoccupée.

    C'est à dire:

    Poste:
    1 poste1 01/01/2014 31/12/2014

    Affectation
    1 01/02/2014 31/02/2014 1
    2 20/02/2014 20/03/2014 1
    3 01/06/2014 31/06/2014 1

    Je veux donc récupérer a la fin
    Poste DateDeb DateFin
    Poste1 01/01/2014 01/02/2014
    Poste1 20/03/2014 01/06/2014
    Poste1 01/07/2014 31/22/2014

    Je ne parviens pas a faire la requête ou procédure qui me permettra de récupérer ce résultat, pouvez vous m'aider à construire ma requête.
    Merci

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Il vous faut une table calendrier.
    Ensuite il faut passer par la méthode de Tabibitosan.

    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    with poste (id_poste, nom, datedebut, datefin) as
    (
    select 1, 'poste1', date '2014-01-01', date '2014-12-31' from dual
    )
      ,  situation (id_sit, datedebsit, datefinsit, id_poste) as
    (
    select 1, date '2014-02-01', date '2014-02-28', 1 from dual union all
    select 2, date '2014-02-20', date '2014-03-20', 1 from dual union all
    select 3, date '2014-06-01', date '2014-06-30', 1 from dual
    )
      , calendrier (id_poste, cal_jour) as
    (
        select id_poste, datedebut + level - 1
          from poste
    connect by level <= datefin - datedebut + 1
    )
      ,  ident (id_poste, cal_jour, attribue) as
    (
    select cal.id_poste, cal.cal_jour
         , case
             when exists (select null
                            from situation sit
                           where sit.id_poste = cal.id_poste
                             and cal.cal_jour between sit.datedebsit and sit.datefinsit)
             then 1
             else 0
           end
      from calendrier cal
    )
      , regroup (id_poste, cal_jour, attribue, grp) as
    (
    select id_poste, cal_jour, attribue
         , row_number() over(                      order by cal_jour asc)
         - row_number() over(partition by attribue order by cal_jour asc) 
      from ident
    )
      select id_poste
           , min(cal_jour) as jour_deb
           , max(cal_jour) as jour_fin
        from regroup
       where attribue = 0
    group by id_poste, grp
    order by id_poste, jour_deb;
     
      ID_POSTE JOUR_DEB            JOUR_FIN          
    ---------- ------------------- -------------------
             1 2014-01-01 00:00:00 2014-01-31 00:00:00 
             1 2014-03-21 00:00:00 2014-05-31 00:00:00 
             1 2014-07-01 00:00:00 2014-12-31 00:00:00
    Le when exists dans le case n'est pas super élégant cela dit.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 39
    Par défaut
    Ton example fonctionne mais lorsque j'essaie de l'appliquer à mon exemple particulier la requête se lance mais tourne comme si il y avait une boucle infini

    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    With 
    poste(id_poste, nom, datedebut, datefin) AS
    (
      select 
      CA2IPOSITION.SYSID,
      CA2IPOSITION.CA2ITITLE,
      CA2IPOSITION.CA2IACTUALSTARTDATE,
      CA2IPOSITION.CA2IACTUALENDDATE
      from CA2IPOSITION
    ),
    Situation(datedebsit, datefinsit, id_poste) AS
    (
      Select 
      PSALSIT.SA_DATDEBSIT,
      PSALSIT.SA_DATFINSIT,
      PSALSIT.CA2IPOSTEPRINCIPAL_ID
      from PSALSIT
     
    ),
    calendrier (id_poste, cal_jour) as
    (
        select 
        id_poste,
        datedebut + level - 1
        from poste
        connect by level <= datefin - datedebut + 1
    ),
    ident (id_poste, cal_jour, attribue) as
    (
        select
        cal.id_poste,
        cal.cal_jour
         , case
             when exists (select null
                            from situation sit
                           where sit.id_poste = cal.id_poste
                             and cal.cal_jour between sit.datedebsit and sit.datefinsit)
             then 1
             else 0
           end
      from calendrier cal
    )
    , regroup (id_poste, cal_jour, attribue, grp) as
    (
        select id_poste, cal_jour, attribue
             , row_number() over(                      order by cal_jour asc)
             - row_number() over(partition by attribue order by cal_jour asc) 
          from ident
    )
      select id_poste
           , min(cal_jour) as jour_deb
           , max(cal_jour) as jour_fin
        from regroup
       where attribue = 0
    group by id_poste, grp
    order by id_poste, jour_deb;
    Ou es-ce que j'ai fait une erreur?
    Merci de ton aide.

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

    Informations forums :
    Inscription : Août 2008
    Messages : 2 953
    Par défaut
    Oui il y a une sorte de boucle infinie (enfin peut être pas infinie mais très très très grande en fonction de la taille de la table poste et des bornes).
    Avec une ligne le simple CONNECT BY fonctionne :
    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
    SQL> with poste (id_poste, nom, datedebut, datefin) as
      2  (
      3  select 1, 'poste1', date '2014-01-01', date '2014-01-05' from dual
      4  ),
      5   calendrier (id_poste, cal_jour) as
      6  (
      7      select id_poste, datedebut + level - 1
      8        from poste
      9  connect by level <= datefin - datedebut + 1
     10  )
     11  select * from calendrier;
     
      ID_POSTE CAL_JOUR
    ---------- --------
             1 01/01/14
             1 02/01/14
             1 03/01/14
             1 04/01/14
             1 05/01/14
    Mais avec 2 lignes dans poste on obtient :
    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    SQL> with poste (id_poste, nom, datedebut, datefin) as
      2  (
      3  select 1, 'poste1', date '2014-01-01', date '2014-01-05' from dual union all
      4  select 2, 'poste2', date '2014-02-01', date '2014-02-05' from dual
      5  ),
      6   calendrier (id_poste, cal_jour) as
      7  (
      8      select id_poste, datedebut + level - 1
      9        from poste
     10  connect by level <= datefin - datedebut + 1
     11  )
     12  select * from calendrier;
     
      ID_POSTE CAL_JOUR
    ---------- --------
             1 01/01/14
             1 02/01/14
             1 03/01/14
             1 04/01/14
             1 05/01/14
             2 05/02/14
             2 04/02/14
             1 05/01/14
             2 05/02/14
             2 03/02/14
             1 04/01/14
     
      ID_POSTE CAL_JOUR
    ---------- --------
             1 05/01/14
             2 05/02/14
             2 04/02/14
             1 05/01/14
             2 05/02/14
             2 02/02/14
             1 03/01/14
             1 04/01/14
             1 05/01/14
             2 05/02/14
             2 04/02/14
     
      ID_POSTE CAL_JOUR
    ---------- --------
             1 05/01/14
             2 05/02/14
             2 03/02/14
             1 04/01/14
             1 05/01/14
             2 05/02/14
             2 04/02/14
             1 05/01/14
             2 05/02/14
             2 01/02/14
             1 02/01/14
     
      ID_POSTE CAL_JOUR
    ---------- --------
             1 03/01/14
             1 04/01/14
             1 05/01/14
             2 05/02/14
             2 04/02/14
             1 05/01/14
             2 05/02/14
             2 03/02/14
             1 04/01/14
             1 05/01/14
             2 05/02/14
     
      ID_POSTE CAL_JOUR
    ---------- --------
             2 04/02/14
             1 05/01/14
             2 05/02/14
             2 02/02/14
             1 03/01/14
             1 04/01/14
             1 05/01/14
             2 05/02/14
             2 04/02/14
             1 05/01/14
             2 05/02/14
     
      ID_POSTE CAL_JOUR
    ---------- --------
             2 03/02/14
             1 04/01/14
             1 05/01/14
             2 05/02/14
             2 04/02/14
             1 05/01/14
             2 05/02/14
     
    62 rows selected.
     
    SQL>
    Ce qui ne convient pas du tout, avec seulement 2 lignes sur 5 jours...

    Il faut utiliser une vrai table calendrier comme celle proposée par Waldar, ou alors générer le calendrier comme ceci :
    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
    25
    26
    27
    28
    29
    30
    31
    32
    SQL> with poste (id_poste, nom, datedebut, datefin) as
      2  (
      3  select 1, 'poste1', date '2014-01-01', date '2014-01-05' from dual union all
      4  select 2, 'poste2', date '2014-02-01', date '2014-02-05' from dual
      5  ),
      6   calendrier (id_poste, cal_jour) as
      7  (
      8      select id_poste, datedebut + level - 1
      9        from poste
     10  connect by level <= datefin - datedebut + 1
     11     AND PRIOR id_poste = id_poste
     12     AND PRIOR sys_guid() IS NOT NULL
     13  )
     14  select * from calendrier
     15  ;
     
      ID_POSTE CAL_JOUR
    ---------- --------
             1 01/01/14
             1 02/01/14
             1 03/01/14
             1 04/01/14
             1 05/01/14
             2 01/02/14
             2 02/02/14
             2 03/02/14
             2 04/02/14
             2 05/02/14
     
    10 rows selected.
     
    SQL>

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    39
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 39
    Par défaut
    Bonjour,

    Jusqu'à la partie ident cela fonctionne
    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    2c9e86034941ac2e014956fa2104290a	agent comptable junior	27/10/14	1
    2c9e86034941ac2e014956fa2104290a	agent comptable junior	28/10/14	1
    2c9e86034941ac2e014956fa2104290a	agent comptable junior	29/10/14	1
    2c9e86034941ac2e014956fa2104290a	agent comptable junior	30/10/14	1
    2c9e86034941ac2e014956fa2104290a	agent comptable junior	31/10/14	1
    2c9e86034941ac2e014956fa2104290a	agent comptable junior	01/11/14	1
    2c9e86034941ac2e014956fa2104290a	agent comptable junior	02/11/14	1
    2c9e86034941ac2e014956fa2104290a	agent comptable junior	03/11/14	1
    2c9e86034941ac2e014956fa2104290a	agent comptable junior	04/11/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	16/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	17/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	18/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	19/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	20/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	21/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	22/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	23/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	24/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	25/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	26/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	27/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	28/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	29/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	30/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	31/12/14	1
    2c9e86034985c2e701498aaebff8730f	AI test	01/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	02/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	03/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	04/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	05/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	06/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	07/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	08/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	09/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	10/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	11/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	12/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	13/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	14/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	15/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	16/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	17/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	18/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	19/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	20/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	21/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	22/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	23/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	24/01/15	1
    2c9e86034985c2e701498aaebff8730f	AI test	25/01/15	1
    Mais dès que je tente la partie regroupement je me retrouve avec une liste vide
    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    with
     
    posteSit(idPoste,nom, debutSit, FinSit) AS
    (
      select CA2IPOSITION.sysid, CA2IPOSITION.CA2ITITLE,SA_DATDEBSIT,NVL(SA_DATFINSIT, SA_DATDEBSIT)
      from CA2IPOSITION,psalsit
      where CA2IPOSITION.sysid=psalsit.CA2IPOSTEPRINCIPAL_ID
      and CA2IPOSITION.CA2ITITLE!='Poste test 3'----------------------------A supprimer
      ORDER BY  CA2IPOSITION.CA2ITITLE,SA_DATDEBSIT,SA_DATFINSIT
     
     
    )
     ,
      calendrier (idposte,nom, cal_jour) as
    (
        select idposte,nom, debutSit + level - 1
            from posteSit
       connect by level <= FinSit - debutSit +1
         AND PRIOR idposte = idposte
         AND PRIOR sys_guid() IS NOT NULL
     
    )
    ,  ident (idposte,nom, cal_jour, attribue) as
    (
    select distinct cal.idposte,cal.nom, cal.cal_jour
         , case
             when exists (select null
                            from posteSit sit
                           where sit.idposte = cal.idposte
                             and cal.cal_jour between sit.debutSit and sit.FinSit)
             then 1
             else 0
           end
      from calendrier cal
      order by cal.nom, cal.cal_jour 
    )
    , regroup (idposte, cal_jour, attribue, grp) as
    (
        select idposte, cal_jour, attribue
             , row_number() over(                      order by cal_jour asc)
             - row_number() over(partition by attribue order by cal_jour asc) 
          from ident
    )
      select idposte
           , min(cal_jour) as jour_deb
           , max(cal_jour) as jour_fin
        from regroup
       where attribue = 0
    group by idposte, grp
    order by idposte, jour_deb;
    Une idée de l'endroit ou je me trompe?
    Merci de votre aide

  6. #6
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Il faut rajouter l'id_poste dans les partition by :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    , regroup (idposte, cal_jour, attribue, grp) as
    (
        select idposte, cal_jour, attribue
             , row_number() over(partition by id_poste           order by cal_jour asc)
             - row_number() over(partition by id_poste, attribue order by cal_jour asc) 
          from ident
    )

Discussions similaires

  1. Requête Sql qui regroupe par date
    Par stade13 dans le forum Langage SQL
    Réponses: 10
    Dernier message: 04/02/2013, 17h51
  2. Requête sql regroupement de dates
    Par rocs dans le forum Langage SQL
    Réponses: 1
    Dernier message: 28/07/2005, 16h40
  3. SQL - Regrouper des enregistrements...
    Par Régent dans le forum Langage SQL
    Réponses: 6
    Dernier message: 06/02/2005, 23h42
  4. Réponses: 5
    Dernier message: 29/09/2004, 11h05
  5. Réponses: 8
    Dernier message: 05/05/2004, 12h30

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