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 :

Souci pour le calcul de la moyenne dans une table [12c]


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Décembre 2008
    Messages
    80
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 80
    Par défaut Souci pour le calcul de la moyenne dans une table
    bonjour,

    j'ai une table de solde avec cette structure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CREATE TABLE "COMPTES" 
       ("ID_COMPTE" NUMBER not null, 
    	"DATE_JOUR" DATE not null, 
    	"SOLDE" NUMBER(18,5),
      CONSTRAINT pk_cpt PRIMARY KEY(ID_COMPTE,DATE_JOUR));
    je dois calculer la moyenne des soldes pour chaque mois (somme des soldes/nombre total des jours du mois en question), mais je sèche car il n'y a pas de lignes qui correspondent aux week-ends et aux jours fériés, et dans ce cas là, la valeur du solde = valeur du solde de j-1 (exemple : vendredi le solde=100 , samedi =100,dimanche=solde ).
    je ne sais pas comment m'y prendre pour le faire avec une requête sql
    si quelqu'un peut m'orienter
    je vous remercie beaucoup

  2. #2
    Membre Expert
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 176
    Par défaut
    Bonjour,

    Il faut générer une table des jours pour "combler" les jours manquants, puis utiliser la fonction analytique LAST_VALUE pour aller récupérer le solde du jour précédent le plus proche. Voici la requête:

    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
    with fourchette_date
    as (select min(date_jour) min_date, max(date_jour) max_date
        from comptes
       ),
    calendrier as (select min_date + level date_cal
                   from fourchette_date
                   connect by level <= max_date - min_date + 1
                  ),
    soldes as (              
    select ca.date_cal, 
           nvl(co.id_compte, last_value(co.solde ignore nulls) over (order by ca.date_cal rows between unbounded preceding and 1 preceding)) solde
    from calendrier ca
    left join comptes co
    on (ca.date_cal = co.date_jour)
    )
    select to_char(date_cal, 'YYYY-MM') mois,
           avg(solde) moyenne
    from soldes
    group by to_char(date_cal, 'YYYY-MM')
    order by 1;
    Si tu dois le faire par ID_COMPTE c'est un peu plus compliqué.

  3. #3
    Membre confirmé
    Inscrit en
    Décembre 2008
    Messages
    80
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 80
    Par défaut
    Bonjour,
    merci beaucoup d'avoir répondu.
    j'ai créé une table calendrier, en suivant ce topic , afin de récupérer les jours manquants
    https://www.developpez.net/forums/d1...-jours-feries/


    là je travaille avec ta requête, merci de m'avoir orienté.

  4. #4
    Membre confirmé
    Inscrit en
    Décembre 2008
    Messages
    80
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 80
    Par défaut
    Bonsoir vanagreg
    effectivement j'ai besoin de calculer la moyenne pour chaque mois et pour chaque compte
    j'ai modifié ta requête de la sorte :

    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
    with fourchette_date
    as (select min(date_jour) min_date, max(date_jour) max_date
        from comptes
        group by (to_char(date_jour,'mm/yyyy'))
       ),
    calendrier as (select min_date + level date_cal
                   from fourchette_date
                   connect by level <= max_date - min_date + 1
                  ),
    soldes as (              
    select ca.date_cal,co.id_compte,
           nvl(co.id_compte, last_value(co.solde ignore nulls) over (partition by co.id_compte order by ca.date_cal rows between unbounded preceding and 1 preceding)) solde
    from calendrier ca
    left join comptes co
    on (ca.date_cal = co.date_jour)
    )
    select id_compte,to_char(date_cal, 'YYYY-MM') mois,
           avg(solde) moyenne
    from soldes
    group by to_char(date_cal, 'YYYY-MM'),id_compte
    order by 1;
    mais je ne suis pas sure de moi car je n'ai jamais utilisé les requête de type over et partition , est ce que ça te parait correct ce que j'ai fait ?
    merci beaucoup

  5. #5
    Membre Expert
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 176
    Par défaut
    Bonjour,

    Ce n'est pas si simple. Il faut faire un PARTITION OUTER, c'est-à-dire une jointure externe partitionnée. Oracle possède cette fonctionnalité que d'autres SGBDR n'ont pas. En gros, pour chaque id_compte, il faut que tu puisses combler tous les jours manquants. Si tu fais une simple jointure externe sur la date, alors les jours manquants seront présents mais indépendamment du id_compte. Il faut donc "partitionner" ces jours manquants pour chaque id_compte, et c'est là que le PARTITION OUTER entre en scène.

    Voici la requête:

    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
    with fourchette_date 
    as (select min(date_jour) min_date, max(date_jour) max_date 
        from comptes 
       ), 
    calendrier as (select min_date + level - 1 date_cal 
                   from fourchette_date 
                   connect by level <= max_date - min_date + 1 
                  ), 
    soldes as (               
    select co.id_compte,
           ca.date_cal, 
           coalesce(co.solde, last_value(co.solde ignore nulls) over (partition by co.id_compte order by ca.date_cal rows between unbounded preceding and 1 preceding), 0) solde 
    from comptes co
    partition by (co.id_compte)
    right join calendrier ca
    on (ca.date_cal = co.date_jour) 
    ) 
    select id_compte,
           to_char(date_cal, 'YYYY-MM') mois, 
           avg(solde) moyenne 
    from soldes 
    group by id_compte, to_char(date_cal, 'YYYY-MM') 
    order by 1, 2;
    Tu observes que le PARTITION OUTER se traduit ainsi dans le bloc "soldes":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    from comptes co
    partition by (co.id_compte)
    right join calendrier ca
    on (ca.date_cal = co.date_jour)
    Je partitionne donc ma jointure sur la date par id_compte, ce qui ajoutera les jours manquants de chaque mois pour chaque id_compte. Ensuite oui, il faut ajouter partition by co.id_compte dans la clause OVER de la fonction LAST_VALUE pour que la valeur soit récupérée par id_compte.
    Je n'ai pas tes données donc je ne peux pas tester cette requête.

  6. #6
    Membre confirmé
    Inscrit en
    Décembre 2008
    Messages
    80
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 80
    Par défaut
    Bonjour vanagreg,

    merci pour ton aide. alors comme j'étais vraiment perdue,j'ai opté pour une solution longue mais simple, en s'inspirant de ta première solution.
    1. j'ai crée une table de calendrier
    2. j'ai crée une vue basée sur les tables compte et calendrier ,qui ajoute les dates manquante
    3. une requête sur cette vue qui utilise last_value

    ça m'a aidé, mais comme ta dernière requête est plus propre, je vais travailler dessus.

    En tout cas , c'est grâce à l'efficacité de tes réponses que j'ai pu sortir avec un résultat, que j'espère optimiser dans les prochains jours.

    Merci!

  7. #7
    Membre confirmé
    Inscrit en
    Décembre 2008
    Messages
    80
    Détails du profil
    Informations forums :
    Inscription : Décembre 2008
    Messages : 80
    Par défaut
    Bonjour,
    en fait j'ai rien modifié à la requête , elle fonctionne. GENIAL!
    merci encore pour ton aide précieuse.

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

Discussions similaires

  1. Comment calculer la mesure "cout" dans une table de fait
    Par andy888 dans le forum Conception/Modélisation
    Réponses: 6
    Dernier message: 03/10/2013, 17h30
  2. [WD17] Calcul vitesse moyenne dans une table
    Par roultabille dans le forum WinDev
    Réponses: 4
    Dernier message: 09/01/2013, 10h24
  3. [XL-2003] Calcul de moyenne dans une plage avec condition
    Par flo21000 dans le forum Excel
    Réponses: 7
    Dernier message: 24/07/2009, 19h31
  4. calcul entre deux champs dans une table
    Par pomar dans le forum Access
    Réponses: 7
    Dernier message: 29/11/2006, 18h27
  5. [SQL] calcul de plusieurs variables dans une table
    Par guillaumeIOB dans le forum PHP & Base de données
    Réponses: 7
    Dernier message: 12/03/2006, 21h53

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