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

Langage SQL Discussion :

Problème de somme


Sujet :

Langage SQL

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2002
    Messages : 560
    Points : 148
    Points
    148
    Par défaut Problème de somme
    Bonjour,
    J'ai un petit problème avec la requête suivante sous ORACLE 10 g :

    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
     
    select cl.c_client, cl.l_client, f.c_fact, f.d_emission_fact, f.d_deb_factu, f.d_fin_fact, lf.c_id_fact, lf.l_volume_facture,
    sum(case lf.m_forfait 
        when 0 then lf.m_prix_unit*lf.m_volume_facture   
        else lf.m_forfait 
        end) as s 
        from ligne_facturation lf, composant c, facture f, engagement e, client cl
          where lf.l_volume_facture = c.l_composant
          and e.c_id_engag = f.c_id_engag
          and cl.c_id_client = e.c_id_client
          and lf.c_id_fact = f.c_id_fact
          and f.d_emission_fact >= '31/12/2008'
        group by cl.c_client, cl.l_client, f.c_fact, f.d_emission_fact,    f.d_deb_factu, f.d_fin_fact, lf.c_id_fact, 
    lf.l_volume_facture--, lf.m_volume_facture, lf.m_prix_unit
          order by f.c_fact
    Cela vient de la partie qui fait la somme avec fonction SUM.

    En raisonnant sur une facture f.c_fact j'ai par exemple le résultat suivant où la deuxième ligne est fausse :
    --------------------------------------------
    C_FACT L_VOLUME_FACT S
    12/12/1 Composant2 21.28
    12/12/1 Composant1 157.5
    12/12/1 Composant3 1.63
    --------------------------------------------

    Voici une vue sur la même facture sur la table LIGNE_FACTURATION :

    ---------------------------------------------------
    L_VOLUME_FACTURE M_PRIX_UNIT M_VOLUME_FACTURE M_FORFAIT
    Composant1 1.5 10 0
    Composant2 1.52 14 0
    Composant1 1.5 8 0
    Composant3 0 0 1.63
    Composant1 1.5 7 0
    Composant1 1.5 10 0
    -----------------------------------------------------
    La ligne "12/12/1 Composant1 157.5" est fausse.
    En effet j'attends à avoir comme montant :
    1.5*10+1.5*8+1.5*7+1.5*10=50.5
    Or j'obtiens 157.5 !! Voyez-vous le problème dans la requête ?

    Merci pour votre aide.

  2. #2
    Membre émérite Avatar de pacmann
    Homme Profil pro
    Consulté Oracle
    Inscrit en
    Juin 2004
    Messages
    1 626
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consulté Oracle
    Secteur : Distribution

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Points : 2 845
    Points
    2 845
    Par défaut
    Salut !

    Si tu n'obtiens pas les résultats, c'est peut être que ta jointure multiplie des lignes.
    Pour faire un test, tu peux enlever le group by et afficher le détail pour cette facture... ça te permettra de vérifier cette hypothèse.
    (don en rajoutant un prédicat dans le where)

  3. #3
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    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 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    Euh... à moins qu'Oracle soit fantaisiste, la syntaxe normalisée d'un CASE est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    CASE
      WHEN colonne = valeur THEN valeur
      WHEN ...
       ELSE valeur
    END
    J'en profite aussi pour rappeler que la syntaxe normalisée pour les jointures depuis 1992 est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    FROM table1
    JOIN table 2 ON condition de jointure
    Si f.d_emission_fact est, comme il se devrait, de type DATE, celle-ci doit être au format AAAA/MM/JJ et donc la condition de restriction (WHERE) doit respecter cet ordre.

    J'ai remis en forme et normalisé 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
    SELECT cl.c_client, cl.l_client, 
      f.c_fact, f.d_emission_fact, f.d_deb_factu, f.d_fin_fact, 
      lf.c_id_fact, lf.l_volume_facture,
      sum(case 
        when lf.m_forfait = 0 then lf.m_prix_unit * lf.m_volume_facture   
        else lf.m_forfait 
      end) AS s 
    FROM ligne_facturation lf
    INNER JOIN composant c ON lf.l_volume_facture = c.l_composant
    INNER JOIN facture f ON lf.c_id_fact = f.c_id_fact
      INNER JOIN engagement e ON e.c_id_engag = f.c_id_engag
        INNER JOIN client cl ON cl.c_id_client = e.c_id_client
    WHERE f.d_emission_fact >= '2008/12/31'
    GROUP BY cl.c_client, cl.l_client, 
      f.c_fact, f.d_emission_fact, f.d_deb_factu, f.d_fin_fact, 
      lf.c_id_fact, lf.l_volume_facture, lf.m_volume_facture, lf.m_prix_unit
    ORDER BY f.c_fact
    C'est quand même plus facile à lire comme ça non ?
    A essayer mais je n'ai pas trouvé d'erreur dans la requête donc ça ne doit toujours pas donner ce que tu cherches.

  4. #4
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    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 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Euh... à moins qu'Oracle soit fantaisiste, la syntaxe normalisée d'un CASE est :
    CASE <valeur> WHEN fonctionne également (testé sous Oracle, Sybase et SQL Server) sans problème.

    Extrait de la doc MS :
    Simple CASE expression:
    CASE input_expression
    WHEN when_expression THEN result_expression [ ...n ]
    [ ELSE else_result_expression ]
    END

    Searched CASE expression:
    CASE
    WHEN Boolean_expression THEN result_expression [ ...n ]
    [ ELSE else_result_expression ]
    END
    Je ne sais pas ce que la norme préconise.

    Si f.d_emission_fact est, comme il se devrait, de type DATE, celle-ci doit être au format AAAA/MM/JJ et donc la condition de restriction (WHERE) doit respecter cet ordre.
    Non, la date est au format date. La conversion implicite elle dépend du paramétrage de la base, de la session et du client.

    C'est pour cette raison qu'il faut se forcer à faire les conversions explicites avec les dates. Avec Oracle on peut utiliser soit la fonction to_date soit directement le mot date avec le format ISO (qui est de la forme YYYY-MM-DD et non pas YYYY/MM/DD).
    Donc ici par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    f.d_emission_fact >= to_date('31/12/2008', 'dd/mm/yyyy')
    OU
    f.d_emission_fact >= date '2008-12-31'
    Pour le problème initial, partez de la table des lignes de facture (en spécifiant une ou deux factures où vous avez le problème) et reconstruisez votre requête en rajoutant les jointures une par une et en contrôlant la cohérence de vos résultats.

  5. #5
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 109
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 109
    Points : 28 436
    Points
    28 436
    Par défaut
    Les deux syntaxes de CASE sont conformes à la norme...
    En revanche DECODE() ne l'est pas

Discussions similaires

  1. [Oracle] Problème requête somme
    Par baptus dans le forum Langage SQL
    Réponses: 24
    Dernier message: 23/03/2006, 08h33
  2. CR Problème de somme
    Par canardpc dans le forum SAP Crystal Reports
    Réponses: 2
    Dernier message: 28/02/2006, 16h50
  3. Probléme avec somme de l'indépendante
    Par aminbouassida dans le forum Access
    Réponses: 2
    Dernier message: 30/09/2005, 15h18
  4. Problème de somme avec Qreport
    Par Oluha dans le forum Bases de données
    Réponses: 2
    Dernier message: 16/09/2005, 11h23
  5. - [procédure stockée] - Problème de Somme
    Par korrigann dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 20/05/2003, 11h51

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