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 :

Reconstitution de périodes


Sujet :

SQL Oracle

  1. #1
    Nouveau Candidat au Club
    Femme Profil pro
    stat
    Inscrit en
    Septembre 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : stat

    Informations forums :
    Inscription : Septembre 2017
    Messages : 3
    Points : 1
    Points
    1
    Par défaut Reconstitution de périodes
    Bonjour,

    J'interroge des tables oracle via SQL plus. J'aurai souhaité reconstituer des périodes. Je m'explique.

    Est ce que quelqu'un saurait me dire comment je peux reconstituer des périodes qui peuvent être coupées de 3 jours.
    Ma table contient 3 variables : Identifiant, début période et fin période
    Un tri est réalisé par identifiant, par début de période et par fin de période

    Voici un exemple

    table intial
    PAT DEB FIN
    1 20160101 20160106
    1 20160108 20160110
    1 20160111 20160115
    1 20160201 20160210
    2 20160501 20160504
    2 20160506 20160510

    ce que je veux en sortie : Je considère que la période est la même lorsque la différence entre le début de la période (ligne l +1) et la fin de la période (ligne l) est inférieure ou égale à 3
    PAT DEB FIN
    1 20160101 20160115
    1 20160201 20160210
    2 20160501 20160510



    une idée en SQL ?

    d'avance merci !

  2. #2
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Je pense qu'il faut une CTE. Je ne suis pas du tout à l'aise avec ça vu que je travaille principalement avec MySQL et que ça n'y existe pas mais ça doit être un truc de ce style :
    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
    WITH periodes_groupees AS
    (
    	SELECT t1.PAT, 
    		t1.DEB DEB_t1, 
    		t1.FIN FIN_t1,
    		t2.DEB DEB_t2,
    		t2.FIN FIN_t2
    	FROM la_table t1
    	LEFT OUTER JOIN la_table t2 ON t2.PAT = t1.PAT
    	WHERE TO_DATE(t2.DEB, 'YYYYMMDD') - TO_DATE(t1.FIN, 'YYYYMMDD') < 4
    )
    SELECT PAT, 
    	DEB_t1 DEB,
    	FIN_t2 FIN
    FROM periodes_groupees
    ORDER BY PAT, DEB, FIN
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  3. #3
    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
    Une piste :
    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
    with t as (
    select 1 as pat, 20160101 as deb, 20160106 as fin from dual union all
    select 1, 20160108, 20160110 from dual union all
    select 1, 20160111, 20160115 from dual union all
    select 1, 20160201, 20160210 from dual union all
    select 2, 20160501, 20160504 from dual union all
    select 2, 20160506, 20160510 from dual
    ),
           regroupe as (
    select pat, deb, fin
         , row_number() over(partition by pat order by deb)
         - case when lag(deb) over(partition by pat order by deb) is null then 0
                when deb - lag(fin,1,deb) over(partition by pat order by deb) > 3 then 0
                else row_number() over(partition by pat order by deb) -1 
            end as grp
      from t
    )
    select pat, min(deb) as min_deb, max(fin) as max_deb
      from regroupe
     group by pat, grp
     order by pat, min_deb
     
           PAT    MIN_DEB    MAX_DEB
    ---------- ---------- ----------
             1   20160101   20160115
             1   20160201   20160210
             2   20160501   20160510

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 763
    Points : 52 554
    Points
    52 554
    Billets dans le blog
    5
    Par défaut
    Élargissez vos périodes sur la borne basse en y ajoutant 3 jours et utilisez une des requêtes d'agrégation d'intervalle que j'ai donné dans ce papier :
    https://blog.developpez.com/sqlpro/p...alles_en_sql_1

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    99
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 99
    Points : 110
    Points
    110
    Par défaut
    Citation Envoyé par skuatamad Voir le message
    Une piste :
    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
    with t as (
    select 1 as pat, 20160101 as deb, 20160106 as fin from dual union all
    select 1, 20160108, 20160110 from dual union all
    select 1, 20160111, 20160115 from dual union all
    select 1, 20160201, 20160210 from dual union all
    select 2, 20160501, 20160504 from dual union all
    select 2, 20160506, 20160510 from dual
    ),
           regroupe as (
    select pat, deb, fin
         , row_number() over(partition by pat order by deb)
         - case when lag(deb) over(partition by pat order by deb) is null then 0
                when deb - lag(fin,1,deb) over(partition by pat order by deb) > 3 then 0
                else row_number() over(partition by pat order by deb) -1 
            end as grp
      from t
    )
    select pat, min(deb) as min_deb, max(fin) as max_deb
      from regroupe
     group by pat, grp
     order by pat, min_deb
     
           PAT    MIN_DEB    MAX_DEB
    ---------- ---------- ----------
             1   20160101   20160115
             1   20160201   20160210
             2   20160501   20160510
    Attention, si tu ajoute les lignes suivantes dans ta table de départ ça ne fonctionne plus ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    select 1, 20160301, 20160310 from dual union all
    select 1, 20160311, 20160315 from dual union all

  6. #6
    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
    Citation Envoyé par Mystro Voir le message
    Attention, si tu ajoute les lignes suivantes dans ta table de départ ça ne fonctionne plus ...
    Effectivement, plutôt comme ça :
    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
    with t as (
    select 1 as pat, 20160101 as deb, 20160106 as fin from dual union all
    select 1, 20160108, 20160110 from dual union all
    select 1, 20160111, 20160115 from dual union all
    select 1, 20160201, 20160210 from dual union all
    select 1, 20160301, 20160310 from dual union all
    select 1, 20160311, 20160315 from dual union all
    select 2, 20160501, 20160504 from dual union all
    select 2, 20160506, 20160510 from dual
    ),
           detecte_groupe as (
    select pat, deb, fin
         , case when lag(deb) over(partition by pat order by deb) is null then 1
                when deb - lag(fin,1,deb) over(partition by pat order by deb) > 3 then 1
                else  0
            end as flag_grp
      from t
    ),
           regroupe as ( 
    select pat, deb, fin
         , sum(flag_grp) over(partition by pat order by deb) as grp
      from detecte_groupe d
    )
    select pat, min(deb) as min_deb, max(fin) as max_deb
      from regroupe
     group by pat, grp
     order by pat, min_deb

  7. #7
    Nouveau Candidat au Club
    Femme Profil pro
    stat
    Inscrit en
    Septembre 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : stat

    Informations forums :
    Inscription : Septembre 2017
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Merci pour vos rapides retours

    juste une question : pourquoi cela ne fonctionnait pas en ajoutant les 2 lignes de codes

    select 1, 20160301, 20160310 from dual union all
    select 1, 20160311, 20160315 from dual union all

    merci !

  8. #8
    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
    Pour comprendre les étapes intermédiaires particulièrement avec des résultats agrégés, il suffit d'exécuter les différentes étapes une par une sans agrégation.
    Faites donc un select * from regroupe avec la 1ere requête et vous allez constater que la colonne GRP n'est pas correctement valorisée pour la ligne 1, 20160311, 20160315

  9. #9
    Nouveau Candidat au Club
    Femme Profil pro
    stat
    Inscrit en
    Septembre 2017
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : stat

    Informations forums :
    Inscription : Septembre 2017
    Messages : 3
    Points : 1
    Points
    1
    Par défaut
    Ok merci

  10. #10
    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
    Une autre piste avec la clause MODEL.
    Un peu obscure cette clause, mais peut être plus performant pour déterminer le groupe que la solution précédente en 2 étapes :
    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
    with t as (
    select 1 as pat, 20160101 as deb, 20160106 as fin from dual union all
    select 2, 20160501, 20160504 from dual union all
    select 1, 20160111, 20160115 from dual union all
    select 1, 20160201, 20160210 from dual union all
    select 1, 20160301, 20160310 from dual union all
    select 1, 20160108, 20160110 from dual union all
    select 1, 20160311, 20160315 from dual union all
    select 2, 20160506, 20160510 from dual
    ),
           regroupe as (
    select pat, deb, fin, grp
    from t
    model
    partition by (pat)
    dimension by (row_number() over(partition by pat order by deb) rn)
    measures (deb, fin, 0 grp)
    rules (
       grp[rn] = case when deb[cv()] - fin[cv()-1] > 3 then nvl(grp[cv()-1],0)+1 else nvl(grp[cv()-1],0) end
     )
    )
    select pat, min(deb) as min_deb, max(fin) as max_fin
      from regroupe
     group by pat, grp
     order by pat, min_deb

Discussions similaires

  1. Total Cumulé sur période glisante en CR9
    Par nanouille56 dans le forum SAP Crystal Reports
    Réponses: 7
    Dernier message: 12/07/2005, 15h07
  2. analyse "périodes" basées sur des dates.
    Par Yorglaa dans le forum Oracle
    Réponses: 7
    Dernier message: 22/12/2004, 11h39
  3. Chevauchement de période
    Par grunge_ dans le forum Langage SQL
    Réponses: 4
    Dernier message: 25/08/2004, 17h04
  4. [CR] Filtrer pour une période donnée
    Par liberio dans le forum SAP Crystal Reports
    Réponses: 6
    Dernier message: 21/04/2004, 16h32
  5. Calculer la période d'une horloge
    Par barthelv dans le forum Algorithmes et structures de données
    Réponses: 12
    Dernier message: 08/03/2004, 16h39

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