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 :

Claculer un cumul


Sujet :

SQL Oracle

  1. #1
    Membre confirmé
    Inscrit en
    Août 2005
    Messages
    145
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 145
    Par défaut Claculer un cumul
    Bjr,

    J'ai une table avec les champs suivants:

    annee number,
    mois number,
    production number,

    Mon but est de calculer le cumul de production atteint pour chaque mois, par ex: pour le mois de juin 2007, je veux avoir

    annee: 2007
    mois: juin
    production: somme de production de tt les mois entre janvier et juin


    Une idee?

    Merci

    Réda

  2. #2
    Membre confirmé
    Inscrit en
    Août 2005
    Messages
    145
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 145
    Par défaut
    oups, j'ai deja essayé cela, ca donne la somme de la production pour le mois de Juin uniquement, mais mois ce que je veux, c'est avoir pour Juin (par exemple) production de janvier + production de Fervier + production de Mars + ... + production de Juin

  3. #3
    Invité
    Invité(e)
    Par défaut
    Oui j'ai m*** et je viens de supprimer mon message ce qui fait que c'est bizarre.
    Perso, je ferais une fonction pour faire ça, mais il y a sûrement moyen de faire une belle requête avec des fonctions analytique mais je ne maîtrise pas...

  4. #4
    Invité
    Invité(e)
    Par défaut
    un éclair de génie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT a.annee, a.mois, sum(b.prod) 
    FROM ma_table A, ma_table B 
    WHERE a.annee = b.annee  
      AND b.mois <= a.mois 
    GROUP BY a.annee, a.mois ;

  5. #5
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    Et regardez aussi du coté des vues matérialisés

  6. #6
    Expert éminent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    pourquoi pas un trigger qui met à jour la colonne production à chaque nouveau mois inséré ?

  7. #7
    Expert éminent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    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
    CREATE OR REPLACE TRIGGER mon_trigger
    BEFORE INSERT ON ma_table
    REFERENCING OLD AS OLD NEW AS NEW
    FOR EACH ROW
    DECLARE
    PRAGMA AUTONOMOUS_TRANSACTION; -- evite ora-04091
    BEGIN
    IF :new.mois > 1 THEN
      SELECT prod + :new.prod
        INTO :new.prod
        FROM ma_table
       WHERE mois = :new.mois - 1
         AND annee = :new.annee;
    END IF;
    END;
    /
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    insert into ma_table values (2007,1,10);
    insert into ma_table values (2007,2,15);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SQL>select * from ma_table;
     
         ANNEE       MOIS       PROD
    ---------- ---------- ----------
          2007          1         10
          2007          2         25

  8. #8
    Membre expérimenté Avatar de Loyd1974
    Profil pro
    Inscrit en
    Août 2007
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 176
    Par défaut
    En analytique, cela donne ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    WITH t AS (SELECT 2007 AS YEAR, 1 AS MONTH, 1000 AS production FROM dual UNION ALL
                          SELECT 2007, 2, 800 FROM dual UNION ALL
                        SELECT 2007, 3, 500 FROM dual UNION ALL
                        SELECT 2007, 4, 40 FROM dual)
    SELECT YEAR, MONTH, SUM(production) over (ORDER BY YEAR,MONTH)
    FROM t
    Edit: au cas où tu ne serais pas familier avec la clause WITH, ne t'attarde pas dessus, cela me permet juste de me créer un jeu d'essai sans passer par la création d'une table, ce qui est important c'est le SUM(...) OVER (..)

  9. #9
    Expert éminent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    si tu inclus le mois dans la SUM ça ne marche pas comme il veut si je ne m'abuse

  10. #10
    Membre expérimenté Avatar de Loyd1974
    Profil pro
    Inscrit en
    Août 2007
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 176
    Par défaut
    Je ne sais pas, moi, j'ai juste lu :
    Mon but est de calculer le cumul de production atteint pour chaque mois, par ex: pour le mois de juin 2007, je veux avoir

    annee: 2007
    mois: juin
    production: somme de production de tt les mois entre janvier et juin
    Donc, si on prend ma requête cela donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    WITH t AS (SELECT 2007 AS YEAR, 1 AS MONTH, 1000 AS production FROM dual UNION ALL
                          SELECT 2007, 2, 800 FROM dual UNION ALL
                        SELECT 2007, 3, 500 FROM dual UNION ALL
                        SELECT 2007, 4, 40 FROM dual)
    SELECT YEAR, MONTH, SUM(production) over (ORDER BY YEAR,MONTH)
    FROM t  
      
    >
       	YEAR	MONTH	SUM(PRODUCTION)OVER(ORDERBYYEA
    1	2007	1	1000
    2	2007	2	1800
    3	2007	3	2300
    4	2007	4	2340
    Donc pour le mois de mars, j'ai bien production mars +production février + production janvier
    C'est pas cela qu'il veut ?

  11. #11
    Membre expérimenté Avatar de Loyd1974
    Profil pro
    Inscrit en
    Août 2007
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 176
    Par défaut
    oups, je suis fatigué, j'ai écrit une énormité, le vrai code c'est :

    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 t AS (SELECT 2007 AS YEAR, 1 AS MONTH, 1000 AS production FROM dual UNION ALL
                          SELECT 2007, 2, 800 FROM dual UNION ALL
                        SELECT 2007, 3, 500 FROM dual UNION ALL
                        SELECT 2007, 4, 40 FROM dual UNION ALL
                                            SELECT 2006,12,10000 FROM dual)
    SELECT YEAR, MONTH, SUM(production) over (PARTITION BY YEAR ORDER BY YEAR,MONTH) AS cumul
    FROM t  
     
    ce qui donne :
           YEAR    MONTH    CUMUL
    1    2006    12    10000
    2    2007    1    1000
    3    2007    2    1800
    4    2007    3    2300
    5    2007    4    2340
    J'avais oublié de partitionner par l'année, car je pense qu'au mois de janvier 2007 les compteurs repartent à zéro et que tu ne veux pas les données de 2006, sinon, si tu fais janvier 2007 = janvier 2007 + decembre 2006 + novembre 2006 + ... alors, tu n'as pas besoin de partitioner

  12. #12
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Jerome_Mtl Voir le message
    un éclair de génie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT a.annee, a.mois, sum(b.prod) 
    FROM ma_table A, ma_table B 
    WHERE a.annee = b.annee  
      AND b.mois <= a.mois 
    GROUP BY a.annee, a.mois ;
    Et ça, ça ne résoud pas le problème ?

  13. #13
    Expert éminent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    Citation Envoyé par Jerome_Mtl Voir le message
    Et ça, ça ne résoud pas le problème ?

    probablement mais c'est moins performant puisque tu accédes 2 fois à la table... par ailleurs, un trigger est plus "trivial" puisqu'il fait le calcul à l'insertion au lieu de le faire à chaque SELECT

  14. #14
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par orafrance Voir le message
    probablement mais c'est moins performant puisque tu accédes 2 fois à la table... par ailleurs, un trigger est plus "trivial" puisqu'il fait le calcul à l'insertion au lieu de le faire à chaque SELECT
    Bon, ça me rassure.
    Au niveau perf, j'imagine bien qu'un group by avec 2 fois la même table, on a déjà vu mieux. Mais si c'est une petite table, ça peut le faire.

  15. #15
    Expert éminent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    autant prendre l'habitude tout de suite de choisir des solutions performantes

    Note que je n'ai pas vérifié que ta solution fonctionne bien, faut faire le test

  16. #16
    Membre expérimenté Avatar de Loyd1974
    Profil pro
    Inscrit en
    Août 2007
    Messages
    176
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 176
    Par défaut
    Citation Envoyé par orafrance Voir le message
    probablement mais c'est moins performant puisque tu accédes 2 fois à la table... par ailleurs, un trigger est plus "trivial" puisqu'il fait le calcul à l'insertion au lieu de le faire à chaque SELECT
    Juste une précision, le trigger peut être pénalisant si des insert en masse sont effectuées (mais bon, dans le cas présent, j'en doute)
    Par contre, si les données sont modifiées après coup (ce qui me semble être le cas, une table sur laquelle on additionne au fur et à mesure), ton trigger ne prend pas en compte cette possibilité. Il faut peut-être l'adapter pour prendre en compte les UPDATE voire les DELETE.

    La méthode analytique est largement plus performante que d'accéder 2 fois la table effectivement.
    La méthode du trigger permet d'avoir le résultat stockée donc c'est encore plus performant au moment de l'interrogation mais elle comporte un risque si on ne maitrise pas les flux fonctionnels (par exemple, si on ajoute lors de l'insert mais qu'on ne retranche pas lors du delete)

  17. #17
    Expert éminent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    Parfaitement, le compromis pourrait être la vue matérialisée rafraichie ON COMMIT

  18. #18
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    Sauf que cella ne marche pas
    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
     
    drop table ma_table
    /
    create table ma_table(
    annee number,
    mois number,
    prod number
    )
    /
    CREATE OR REPLACE TRIGGER mon_trigger
    BEFORE INSERT ON ma_table
    REFERENCING OLD AS OLD NEW AS NEW
    FOR EACH ROW
    DECLARE
    PRAGMA AUTONOMOUS_TRANSACTION; -- evite ora-04091
    BEGIN
    IF :new.mois > 1 THEN
      SELECT prod + :new.prod
        INTO :new.prod
        FROM ma_table
       WHERE mois = :new.mois - 1
         AND annee = :new.annee;
    END IF;
    END;
    /
    INSERT INTO ma_table VALUES (2007,2,15)
    /
    Et il faut aussi bien préciser à l'utilisateur qu'il doit faire commit après chaque insert
    Avec toute le respect, mais mois je n'appel pas ça une solution

  19. #19
    Expert éminent
    Avatar de orafrance
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    15 967
    Détails du profil
    Informations personnelles :
    Âge : 48
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 15 967
    Par défaut
    euh... si je ne m'abuse pour enregistrer une commande UPDATE, DELETE ou INSERT, il faut faire un COMMIT... j'vois pas bien pourquoi il faudrait le préciser.

    Quand tu rollbackes la ligne n'est pas insérée donc le cumul non plus... j'vois pas en quoi ça ne fonctionne pas

    PS : évidemment dans la solution je considère qu'on n'insére pas mars avant février, je suis sûr que ceux qui passeront sur ce topic sauront adapté l'exemple à leur besoin

  20. #20
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    Citation Envoyé par orafrance Voir le message
    euh... si je ne m'abuse pour enregistrer une commande UPDATE, DELETE ou INSERT, il faut faire un COMMIT... j'vois pas bien pourquoi il faudrait le préciser.
    Sauf si il s'agit d'une transaction
    Essayez quelque chose de type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    insert into ma_table
    select 2007,1,10 from dual
    union 
    select 2007,2,15 from dual

Discussions similaires

  1. Cumuler des valeur indexées
    Par Tlemcen dans le forum Access
    Réponses: 25
    Dernier message: 20/02/2007, 23h29
  2. Cumul de surcharges d'opérateurs
    Par Nats dans le forum C++
    Réponses: 2
    Dernier message: 11/10/2004, 13h37
  3. [DBGrid avec Cumul]Comment réaliser un cumul dans un DBGrid
    Par Eric SAULNIER dans le forum Bases de données
    Réponses: 2
    Dernier message: 21/07/2004, 17h56
  4. selection enregistrement + cumul...
    Par JerBi dans le forum Langage SQL
    Réponses: 2
    Dernier message: 21/07/2004, 11h32
  5. [debutant] les processus se cumulent
    Par glurps dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 17/06/2003, 10h24

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