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 :

DECODE et SUM


Sujet :

SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Développeur informatique
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2007
    Messages : 27
    Par défaut DECODE et SUM
    Bonjour à tous.

    J'ai hérité d'un écran forms pour ajouter une petite évolution. Il s'agit d'une liste de valeurs sur laquelle je dois forcer le résultat d'une requête.

    J'ai une vue qui pointe sur plusieurs tables, dont celles des articles. Et une autre qui pointe sur la table des commandes (entêtes et lignes). Dans ma requête, je fais une jointure pour afficher les quantités attendues par article.

    Pour chaque article, on peut avoir plusieurs variantes. Dans ma requête, je dois afficher la variante, avec les quantités en face. Seulement, pour éviter d'avoir plusieurs fois la même quantité, le client souhaite forcer l'affichage sur la 1ère variante (donc zéro sur les autres).

    Je sais, ça sens le produit cartésien...
    Mais j'ai récupéré le module comme ça et je ne veux pas le réécrire entièrement.


    Résultat attendu :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ARTICLE               VARIANTE   QUANTITE 
    -------               --------   -------- 
    ALGUES DECORATIVES          00         10 
    ALGUES DECORATIVES          01          0 
    ALGUES DECORATIVES          02          0 
    SALICORNES FRAICHES         00         23 
    SALICORNES FRAICHES         01          0 
    SALICORNES FRAICHES         02          0 
    SALICORNES FRAICHES         03          0

    Résultat obtenu :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    ARTICLE               VARIANTE   QUANTITE 
    -------               --------   -------- 
    ALGUES DECORATIVES          00         10 
    ALGUES DECORATIVES          01         10 
    ALGUES DECORATIVES          02         10 
    SALICORNES FRAICHES         00         23 
    SALICORNES FRAICHES         01         23 
    SALICORNES FRAICHES         02         23 
    SALICORNES FRAICHES         03         23

    Je pensais y arriver avec un DECODE, comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT   article, variante, 
             DECODE (variante, '00', (SUM (NVL (quantite, 0))), 0) 
        FROM v_articles, v_commandes 
    WHERE... 
    GROUP BY article, variante;

    Mais ça ne fonctionne pas avec le SUM (j'ai zéro sur toutes les lignes). Il doit bien y avoir une solution...

    Merci d'avance.

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

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

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

    Ton n'implémentation ne t'amène nulle part, puisque DECODE ne s'applique pas sur le groupe, mais sur chaque ligne : il faut que tu fasses la somme tu résultat du DECODE.

    Pour ma culture perso : y a t il une différence de performance entre DECODE et CASE ?

  3. #3
    Membre averti
    Profil pro
    Développeur informatique
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2007
    Messages : 27
    Par défaut DECODE et SUM
    Bonjour Pacmann.

    Merci pour le tuyau, mais ça ne fonctionne pas mieux. J'ai le même résultat.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT   article, variante, 
             SUM (DECODE (variante, '00', quantite, 0)) 
        FROM v_articles, v_commandes 
    WHERE... 
    GROUP BY article, variante;
    J'ai essayé avec le CASE WHEN également. Toujours pareil.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT article, variante,
           CASE variante
               WHEN '00'
                   THEN SUM (quantite)
               ELSE 0
           END AS quantite
        FROM v_articles, v_commandes 
    WHERE... 
    GROUP BY article, variante;
    Sinon, pour répondre à ta question entre DECODE et CASE WHEN, je crois qu'il y a bien une différence de performances.

    Le DECODE est une fonction propre à Oracle qui fonctionne sur toutes les versions.

    Le CASE WHEN est une instruction assez récente et est apparemment plus gourmande sur les versions antérieures à 9i.

    J'ai trouvé ceci.
    SQL - Performances Decode ou Case when ?
    LE SQL de A à Z - Les branchements dans le SQL

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

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

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Par défaut
    Merci à toi pour ta réponse !
    (je suis sûr que des gens diraient d'utiliser systématiquement CASE parce que c'est la norme SQL)

    Pour ton problème, c'est marrant de voir que dans ta première version, les résultats sont tous les même pour un article alors que tu GROUP BY variante :
    Je pense que ta jointure doit looser quelque part.

    Tu peux mettre la requête complète ?

  5. #5
    Membre averti
    Profil pro
    Développeur informatique
    Inscrit en
    Mars 2007
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2007
    Messages : 27
    Par défaut DECODE et SUM
    Pacmann

    Tu veux vraiment la requête complète ? Ici, je l'ai simplifiée au max. Mais c'est comme tu le sens...

    v_liste_article et v_qte_art sont des vues construites avec des requêtes tout aussi complexes.
    Avec des GROUP BY, des DECODE, etc.

    Voici donc notre 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
    24
    25
    26
    27
    28
    SELECT   v.libelle, v.article, v.variante, v.art_no, v.unit_stk,
             v.qte_reel, v.qte_reception,
             SUM (NVL (DECODE (v.variante, '0', s1.qte_a_rec, 0), 0)) quantite 
        FROM article_prix x,
             v_liste_article v,
             (SELECT a.art_no, a.qte_a_rec 
                FROM v_qte_art a 
               WHERE (   (    a.dep = :p_dep
                          AND a.dat_liv = :p_dat_deb
                          AND a.heure_livraison <= :p_heure
                         )
                      OR (a.dep = '4' AND a.dat_liv + 1 = :p_dat_dep)
                     )) s1
       WHERE v.art_no = x.art_no(+)
         AND x.typ_prx(+) = 'PMP'
         AND x.dev(+) = 'EUR'
         AND TRUNC (SYSDATE) BETWEEN dat_deb(+) AND NVL (dat_fin(+),
                                                         TRUNC (SYSDATE))
         AND v.art_no = s1.art_no(+)
    GROUP BY v.libelle,
             v.art_no,
             v.unit_stk,
             v.qte_reel,
             v.qte_reception,
             x.prix,
             v.article,
             v.variante 
    ORDER BY v.libelle;

    Le problème des résultats identiques vient du fait que les jointures ne tiennent pas compte de la variante. Ca nous fait donc un produit cartésien qu'il faut contourner par une astuce...

    A +

  6. #6
    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
    Pour moi ça a l’air d’une requête de type top N : donc analytique. Quelque chose de type :
    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
     
    Select empno, ename, sal, deptno, 
           case rn
             when 1 then sal
             else 0
           end case
    From (       
       Select empno, ename, sal, deptno, 
              row_number() over (partition by deptno order by sal desc) rn
         From emp
         )
     
         EMPNO ENAME             SAL     DEPTNO       CASE
    ---------- ---------- ---------- ---------- ----------
          7839 KING             5000         10       5000
          7782 CLARK            2450         10          0
          7934 MILLER           1300         10          0
          7788 SCOTT            3000         20       3000
          7902 FORD             3000         20          0
          7566 JONES            2975         20          0
          7876 ADAMS            1100         20          0
          7369 SMITH             800         20          0
          7698 BLAKE            2850         30       2850
          7499 ALLEN            1600         30          0
          7844 TURNER           1500         30          0
     
         EMPNO ENAME             SAL     DEPTNO       CASE
    ---------- ---------- ---------- ---------- ----------
          7521 WARD             1250         30          0
          7654 MARTIN           1250         30          0
          7900 JAMES             950         30          0

  7. #7
    Membre Expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Chef de projet en SSII
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 862
    Par défaut
    Citation Envoyé par pacmann Voir le message
    Ton n'implémentation ne t'amène nulle part, puisque DECODE ne s'applique pas sur le groupe, mais sur chaque ligne : il faut que tu fasses la somme tu résultat du DECODE.
    Faux ! Le decode est dans la clause select, elle s'applique donc sur le groupe et non sur chaque ligne :
    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
    SQL> select * from t01;
     
    A B          N
    - - ----------
    A A         10
    A B         20
    A C          5
     
    SQL> select a, b , decode(b, 'A', sum (n), 0)
      2  from t01 group by a, b;
     
    A B DECODE(B,'A',SUM(N),0)
    - - ----------------------
    A A                     10
    A B                      0
    A C                      0

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

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

    Informations forums :
    Inscription : Juin 2004
    Messages : 1 626
    Par défaut
    @PlaineR : effectivement, j'étais complètement à côté de la plaque.

    Concernant le problème principal :
    A moins que je ne sois à nouveau complètement con, si ta jointure ne prend pas en compte la variante, aucun truc ou astuce ne pourra t'aider (ni le décode, ni les fonctions de fenêtrage...)
    Car même si tu arrives à afficher 0 pour les variantes différentes de 00, le résultat de 00 sera faux.

    Table de référence :
    article_no variante
    1 00
    1 01

    Table de détail :
    article_no quantite
    1 10 <= variante 00
    1 20 <= variante 01

    Résultat de la somme "decode" :
    1 00 30 (au lieu de 10)
    1 01 0

    Tu n'as vraiment aucun moyen de faire le lien entre la variante et le détail ?

  9. #9
    Membre expérimenté
    Profil pro
    Inscrit en
    Août 2005
    Messages
    270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 270
    Par défaut
    avec un select qui ramene le code produit et la somme des quantités dans la clause from, cela devrait être assez simple.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select t1.code_article, t2.variante, decode(T2.variante, '00', t3.Qte, 0)
    From articles T1, variante t2, (select code_article, sum(qte) qte from...)t3
    where
    t1.code_article = t3.code_article;
    à peu près... c'est le principe.

  10. #10
    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
    Petit remarque:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Select ...
              SUM (NVL (DECODE (v.variante, '0', s1.qte_a_rec, 0), 0)) 
    Sum(NVL(...,0) ne sert pas à grande chose. NVL(SUM... OUI!
    All aggregate functions except COUNT(*) and GROUPING ignore nulls.

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

Discussions similaires

  1. Pb update avec jointure et sum et decode
    Par lepetitjo dans le forum Langage SQL
    Réponses: 3
    Dernier message: 11/07/2013, 17h55
  2. DECODE ET SUM
    Par AMAJAX dans le forum ODI (ex-Sunopsis)
    Réponses: 2
    Dernier message: 25/04/2008, 17h06
  3. [Optimisation] instruction decode, SUM, * / + -...
    Par Bicnic dans le forum Oracle
    Réponses: 1
    Dernier message: 12/05/2006, 09h21
  4. sum(XPATH) retourne NaN
    Par TOM-Z dans le forum XMLRAD
    Réponses: 4
    Dernier message: 19/03/2003, 13h48
  5. [VBA-E] Fonction sum() dans une cellule
    Par Gonzo dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 16/12/2002, 10h18

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