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 :

Soustraire 2 champs d'une même table


Sujet :

Langage SQL

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2012
    Messages : 127
    Points : 56
    Points
    56
    Par défaut Soustraire 2 champs d'une même table
    Bonjour à tous,

    J'ai une table sous la forme

    id | article | montant | date

    Pour un article X à une Date Y et ce même article à une date Z je souhaite soustraire leur montant (X-Y). Jusque là pas de problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT article , designation, SUM(CASE date WHEN '2016-02-29' THEN montant WHEN '2016-01-31' THEN - montant END) AS DELTA FROM informations GROUP BY article ORDER BY `DELTA` ASC
    Cependant, si pour cet article X n'existait pas à la date Z il va me renvoyer "NULL", or je souhaite obtenir "0" - Montant à date Y.

    Est-ce réalisable ?

  2. #2
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 136
    Points : 38 909
    Points
    38 909
    Billets dans le blog
    9
    Par défaut
    Bonjour,

    Vous devriez formater vos requetes pour les rendre plus facile à lire

    La solution à votre problème consiste à utiliser la fonction COALESCE (arrg1, arg2..., argn) qui renvoie la première valeur non nulle de la liste des arguments entre parenthèses
    dans votre cas "-1 * COALESCE(MONTANT, 0)"

    Ce qui donne quelque chose comme ça (à tester)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT t0.article, 
           t0.designation, 
           t0.montant - coalesce(T1.montant, 0) as delta
    from informations  as T0
    left outer join informations  as T1
      on T1.article = t0.article
     and T1.madate  = '2016-01-31'
    Where t0.madate = '2016-02-29'
    GROUP BY t0.article 
    ORDER BY delta ASC
    Attention, je vois que vous avez appelé l'une de vos colonnes "date" ce qui n'est pas une bonne idée, les mots réservés sont à éviter, car ça vous contraint à les encadrer par des quotes et peut porter à confusion. C'est pourquoi j'ai remplacé par "madate"

  3. #3
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2012
    Messages : 127
    Points : 56
    Points
    56
    Par défaut
    Bonjour à vous et merci pour votre aide.

    Effectivement votre requête fonctionne et me donne le résultat que j'attends.

    Le problème c'est qu'elle met 92s à s'effectuer contre seulement 0.8s pour la mienne mais qui me renvoit des "NULL".

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Affichage des lignes 0 - 24 (total de 5639, Traitement en 92.6397 sec)

  4. #4
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 136
    Points : 38 909
    Points
    38 909
    Billets dans le blog
    9
    Par défaut
    J'ai fait une jointure sur le code article faute de connaitre le DDL de vos tables et index, si la colonne n'est pas indexée et que votre table contient des volumes significatifs, il est normal d'avoir un temps de traitement important. A vous d'adapter la jointure pour utiliser les index
    si vous n'y arrivez pas, communiquez le DDL de votre table et de ses index (CREATE TABLE, CRETAE INDEX)

  5. #5
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2012
    Messages : 127
    Points : 56
    Points
    56
    Par défaut
    Ça ne fait pas si longtemps que ça que je fais de grosses requêtes sql et je dois avouer ne pas avoir tout saisie ce que vous venez de dire.

  6. #6
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 136
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 136
    Points : 38 909
    Points
    38 909
    Billets dans le blog
    9
    Par défaut
    Je veux dire : il faut la description de la table et de ses index pour pouvoir optimiser cette requête
    Quelles sont les colonnes de votre table ? laquelle ou lesquelles constituent la clef primaire unique
    Y a -t- il d'autres clefs uniques ou non ?
    Indiquez aussi le nombre approximatif de lignes contenues dans la table

  7. #7
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    Bonjour,

    Votre requete initiale était plutôt bien, et évitait notamment une jointure externe.
    Cependant, je ne comprend pas la cas que vous exposez. S'il ne manque qu'une date, vous aurez un NULL en sortie de votre CASE, NULL qui sera éliminé lors de l'opération d'agrégat (SUM en l'occurence).
    Je dirais donc que si vous obtenez des NULL en résultat, c'est qu'il n'y a de valeur pour aucune des deux dates spécifiées.
    Dans ce cas, il me semble que vous pouvez simplement ajouter un ELSE 0 à votre CASE.

    Sinon, postez un petit jeu d'essai avec les résultats obtenus, et les résultats attendus afin que l'on comprenne mieux votre problème.

  8. #8
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2012
    Messages : 127
    Points : 56
    Points
    56
    Par défaut
    Alors merci à vous, la requête s'éxécute merveilleusement bien en moins d'1s après quelques modification :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT t0.article, t0.designation, t0.montant - coalesce(T1.montant, 0) as delta from informations as T0 join informations as T1 on T1.article = t0.article and MONTH(T1.date)  = MONTH(DATE_ADD(NOW(), INTERVAL -2 MONTH)) and YEAR(T1.date) = YEAR(DATE_ADD(NOW(), INTERVAL -2 MONTH)) Where t0.date = MONTH(DATE_ADD(NOW(), INTERVAL -1 MONTH)) and YEAR(T0.date) = YEAR(DATE_ADD(NOW(), INTERVAL -1 MONTH)) GROUP BY t0.article ORDER BY delta DESC Limit 20
    Dans phpmyadmin la requête fonctionne très bien ! Mais sous PHP c'est la cata, je n'arrive pas à récupérer mes champs !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    $rqSql_delta = "SELECT t0.article, t0.designation, t0.montant - coalesce(T1.montant, 0) as delta from informations as T0 join informations as T1 on T1.article = t0.article and MONTH(T1.date)  = MONTH(DATE_ADD(NOW(), INTERVAL -2 MONTH)) and YEAR(T1.date) = YEAR(DATE_ADD(NOW(), INTERVAL -2 MONTH)) Where t0.date = MONTH(DATE_ADD(NOW(), INTERVAL -1 MONTH)) and YEAR(T0.date) = YEAR(DATE_ADD(NOW(), INTERVAL -1 MONTH)) GROUP BY t0.article ORDER BY delta DESC Limit 20";
    					$result_delta = mysql_query( $rqSql_delta, $idConnect)
    						     or die( "Exécution requête impossible.");
     
    while ( $row_delta = mysql_fetch_array( $result_delta)) {
    							$article_delta .= $row_delta["article"];
    							$montant_delta .= $row_delta["delta"];
    							$designation_delta .= $row_delta["designation"];
    						}
    Alors après avoir farfouillé sur le net, j'ai vue que mettre des alias pouvait être la solution, malheureusement ça n'a pas fonctionné ( par exemple SELECT t0.article as t0_article et récupérer avec $row_delta["t0_article"]; ).

    Sauriez-vous m'éclairer là dessus également ? Merci !

    EDIT : Quand je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    echo mysql_field_name($result_delta, 0);echo mysql_field_name($result_delta, 1);echo mysql_field_name($result_delta, 2);
    je retrouve bien les noms : article, delta, designation.

  9. #9
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    127
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2012
    Messages : 127
    Points : 56
    Points
    56
    Par défaut
    Problème résolu, j'avais oublié un MONTH(t0.date) dans la requête ! Je mets en résolu, merci à vous !

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

Discussions similaires

  1. Comment soustraire 2 champs d'une même table?
    Par muad'dib dans le forum Langage SQL
    Réponses: 3
    Dernier message: 25/03/2008, 11h55
  2. Update critériel de plusieurs champs d'une même table
    Par Xorbane dans le forum Requêtes et SQL.
    Réponses: 3
    Dernier message: 27/10/2007, 18h12
  3. Conditions sur les champs d'une même table
    Par Pucho dans le forum Modélisation
    Réponses: 10
    Dernier message: 19/10/2007, 17h52
  4. Plusieurs Champs d'une même table dans plusieurs textebox
    Par cyberbiker dans le forum VB 6 et antérieur
    Réponses: 11
    Dernier message: 13/09/2006, 11h32
  5. [Requête] plusieurs champs dans une même table ayants la même source
    Par Christophe93250 dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 25/04/2006, 16h18

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