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 :

Comptage avec valeurs nulles


Sujet :

Langage SQL

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 33
    Points : 23
    Points
    23
    Par défaut Comptage avec valeurs nulles
    Bonjour,

    Je vais essayer d'être le plus clair possible !
    J'ai une table personne et pour chaque personne, j'ai un boulléen qui me dit si elle active ou nom.
    Ensuite, j'ai une table événement. Pour chaque événement, j'ai un champ qui peut contenir moyen faible, moyen ou fort. Chaque événement est rattaché à une personne (il y a l'id de la personne dans la table événement).

    Ce que je voudrais faire, c'est compter le nombre d'événement faible, moyen et fort pour chaque personne active.
    exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    pers_id     evt_urgence            count(e.evt_id)
    1                fort                         0
    1                moyen                        5
    1                faible                       2
    2                fort                         1
    2                moyen                        3
    2                faible                       0
    Actuellement, j'arrive à avoir un chiffrage quand il y a des événements présents mais je n'arrive pas à avoir les valeur nulles (les lignes avec des 0).
    Je fais ça pour les avoir :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    select p.pers_id, decode(e.evt_urgence, 1, 'fort', 2, 'moyen', 3, 'faible'), count(e.evt_id)
            from evenement e
                  left outer join personne p
                          on p.pers_id = e.pers_id
            where p.pers_actif = 1
            GROUP by p.pers, e.evt_urgence
            ORDER BY p.pers, e.evt_urgence asc
    ;
    Avec pour résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    pers_id     evt_urgence            count(e.evt_id)
    1                moyen                        5
    1                faible                       2
    2                fort                         1
    2                moyen                        3
    Je me doute que c'est en rapport avec une jointure mais je ne vois pas comment la faire autrement sans avoir des problèmes de group by

    Quelqu'un peut-il m'aider ?

    D'avance merci !

  2. #2
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Si tu veux toutes les personnes, il faut que ce soit la table de gauche :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT p.pers_id, decode(e.evt_urgence, 1, 'fort', 2, 'moyen', 3, 'faible'), count(e.evt_id)
    FROM personne p
    LEFT OUTER JOIN evenement e ON p.pers_id = e.pers_id
    WHERE p.pers_actif = 1
    GROUP BY p.pers, e.evt_urgence
    ORDER BY p.pers, e.evt_urgence ASC
    Ou alors tu emploies RIGHT OUTER JOIN :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT p.pers_id, decode(e.evt_urgence, 1, 'fort', 2, 'moyen', 3, 'faible'), count(e.evt_id)
    FROM evenement e
    RIGHT OUTER JOIN personne p ON p.pers_id = e.pers_id
    WHERE p.pers_actif = 1
    GROUP BY p.pers, e.evt_urgence
    ORDER BY p.pers, e.evt_urgence ASC
    Par ailleurs, DECODE ne fait pas partie du standard SQL, si j'en crois la liste des mots réservés SQL du site de SQLPro.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 33
    Points : 23
    Points
    23
    Par défaut
    Merci de ton aide CinePhil, ta réponse m'a mis sur une bonne piste.

    J'ai réussi a obtenir le résultat que je souhaitais en effectuant la requête suivante :

    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
    32
    33
    34
    35
    36
     
    select * from 
            (
            SELECT 
                  p.pers_nomprenom as "np",  
                  count(a.evt_id) as "fort"
            FROM personne p
            	LEFT OUTER JOIN (select evt_id, pers_id from evenement where eta_id < 3 and evenement.evt_urgence=1) a 
    			ON p.pers_id = a.pers_id
            WHERE p.pers_actif = 1
            GROUP BY p.pers_nomprenom
            ORDER BY p.pers_nomprenom ASC
            ) natural join
            (
            SELECT 
                  p.pers_nomprenom as "np",   
                  count(b.evt_id) as "moyen"
            FROM personne p
            	LEFT OUTER JOIN (select evt_id, pers_id from evenement where eta_id < 3 and evenement.evt_urgence=2) b 
    		ON p.pers_id = b.pers_id
            WHERE p.pers_actif = 1
            GROUP BY p.pers_nomprenom
            ORDER BY p.pers_nomprenom ASC
            ) natural join
            (
            SELECT 
                  p.pers_nomprenom as "np",   
                  count(c.evt_id) as "faible"
            FROM personne p
            	LEFT OUTER JOIN (select evt_id, pers_id from evenement where eta_id < 3 and evenement.evt_urgence=3) c 
    		ON p.pers_id = c.pers_id
            WHERE p.pers_actif = 1
            GROUP BY p.pers_nomprenom
            ORDER BY p.pers_nomprenom ASC
            )
    ;
    Maintenant, le résultat est celui que j'attendais mais je ne pense pas que ce soit optimisé donc si vous avez des remarques, n'hésitez pas !

  4. #4
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Citation Envoyé par rndhnqz Voir le message
    Maintenant, le résultat est celui que j'attendais mais je ne pense pas que ce soit optimisé donc si vous avez des remarques, n'hésitez pas !
    Avez-vous essayé les requêtes de Cinephil ?

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 33
    Points : 23
    Points
    23
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Avez-vous essayé les requêtes de Cinephil ?
    Oui, mais elles n'étaient pas suffisantes, elles me ramenaient bien le 0 quand une personne n'avait pas d'événement mais pas le détail par niveau d'urgence.

    Je me suis ensuite aidé des ses conseil pour réaliser les jointures et pour avoir le résultat que je décris ci-dessus.

  6. #6
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Ah oui vous avez changé votre besoin depuis la demande initiale.
    Il suffit de faire un simple pivot pour avoir performances et bon résultats :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      SELECT p.pers_id,
             count(case e.evt_urgence when 1 then e.evt_id end) as fort,
             count(case e.evt_urgence when 2 then e.evt_id end) as moyen,
             count(case e.evt_urgence when 3 then e.evt_id end) as faible
        FROM personne p
             LEFT OUTER JOIN evenement e
               ON p.pers_id = e.pers_id
       WHERE p.pers_actif = 1
    GROUP BY p.pers
    ORDER BY p.pers ASC;

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    33
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 33
    Points : 23
    Points
    23
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Ah oui vous avez changé votre besoin depuis la demande initiale.
    Il suffit de faire un simple pivot pour avoir performances et bon résultats :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
      SELECT p.pers_id,
             count(case e.evt_urgence when 1 then e.evt_id end) as fort,
             count(case e.evt_urgence when 2 then e.evt_id end) as moyen,
             count(case e.evt_urgence when 3 then e.evt_id end) as faible
        FROM personne p
             LEFT OUTER JOIN evenement e
               ON p.pers_id = e.pers_id
       WHERE p.pers_actif = 1
    GROUP BY p.pers
    ORDER BY p.pers ASC;
    Merci beaucoup !

    Désolé pour l'évolution du besoin, ça s'est fait au fil des tâtonnements et je ne m'en était pas vraiment rendu compte donc je ne l'ai pas précisé.

    Pour ce qui de votre solution, elle correspond parfaitement à ce que je recherchait. Je ne savais pas qu'on pouvait utiliser le case de cette manière pour faire des count mais c'est vraiment très utile !

    Encore un grand merci à vous et à tout ceux qui ont pris le temps de s'intéresser à ce problème !

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

Discussions similaires

  1. [PostGreSLQ] pb d'UPDATE avec valeur NULL
    Par mellie dans le forum Langage SQL
    Réponses: 3
    Dernier message: 06/03/2006, 10h03
  2. Calcul de stock avec valeure null
    Par nideux dans le forum Access
    Réponses: 3
    Dernier message: 02/12/2005, 11h10
  3. locate avec valeurs nulles
    Par lol_adele dans le forum Bases de données
    Réponses: 13
    Dernier message: 17/10/2005, 13h31
  4. [JDBC] retour de requete sql avec valeur NULL
    Par maxxou dans le forum JDBC
    Réponses: 3
    Dernier message: 13/09/2004, 14h40
  5. Pb requete avec valeurs nulles
    Par James85 dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 12/04/2004, 10h20

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