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

Requêtes MySQL Discussion :

COUNT avec deux WHERE différents


Sujet :

Requêtes MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 123
    Par défaut COUNT avec deux WHERE différents
    Bonjour!
    Dans une requête, je récupère les titres d'ouvrages auxquels sont associés des livres à vendre et des vendeurs. Je veux afficher le nombre de livre invendu pour les vendeurs dont le compte est actif et dont le compte est inactif.

    Pour vous épargner les détails, ce que je veux faire en gros est de compter les lignes d'une même table avec deux condition WHERE différentes, le tout étant imbriqué en sous-requêtes.

    Bref, si mes explications ne sont pas claires, j'ai déjà un code qui fonctionne bien mais je tente de l'optimiser et de le raccourcir :

    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
    37
    38
    39
    40
    41
    42
    43
    44
    SELECT
       O.idOuvrage,
       O.titre,
     
       COUNT(DISTINCT idLivre) AS nbreLivres,
     
       -- Livres invendus, des vendeurs dont le compte est actif
       (SELECT COUNT(idLivre)
          FROM
             livres AS L
             LEFT JOIN vendeurs AS E         ON L.idVendeur = E.idVendeur
          WHERE
             dateVente IS NULL AND
             idOuvrage = O.idOuvrage AND
             -- TRUE pour un compte actif, FALSE pour un compte inactif
             DATEDIFF(DATE_ADD(dateDerniereActivite, INTERVAL 2 YEAR), NOW()) >= 0
          ) AS nbreLivresActifs,
     
       -- Livres invendus des vendeurs dont le compte est inactif
       -- Notez que la sous-requête ci-dessous est quasiment identique à
       -- la première à l'exception de la condition WHERE
       (SELECT COUNT(idLivre)
          FROM
             livres AS L
                LEFT JOIN vendeurs AS E      ON L.idVendeur = E.idVendeur
          WHERE
             dateVente IS NULL AND
             idOuvrage = O.idOuvrage AND
             -- TRUE pour un compte inactif, FALSE pour un compte actif
             DATEDIFF(DATE_ADD(dateDerniereActivite, INTERVAL 2 YEAR), NOW()) < 0
          ) AS nbreLivresInactifs,
     
       GROUP_CONCAT(DISTINCT 
          CONCAT_WS(' ', A.prenom, A.nom)
          ORDER BY A.nom
          SEPARATOR ', '
          ) AS listeAuteurs      
       FROM ouvrages AS O
          LEFT JOIN livres AS L         ON O.idOuvrage = L.idOuvrage
          LEFT JOIN ouvrages_auteurs AS OA   ON O.idOuvrage = OA.idOuvrage
          LEFT JOIN auteurs AS A         ON OA.idAuteur = A.idAuteur
       WHERE L.dateVente IS NULL
       GROUP BY O.idOuvrage
       ORDER BY O.titre
    Merci à l'avance de votre aide!

    La question est longue mais je crois bien que quelqu'un de compétent puisse y répondre sans stagner pendant des heures comme je viens de le faire!

  2. #2
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 292
    Par défaut
    Normalement, ça se fait sans sous-requête, sur ce modèle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SUM(CASE WHEN condition1 THEN 1 ELSE 0 END) AS Nb1,
    SUM(CASE WHEN condition2 THEN 1 ELSE 0 END) AS Nb2,
    Sur ta requête, tu ne montres pas d'où viennent plusieurs colonnes de tes sous-requêtes (idOuvrage, dateDerniereActivite), donc je ne peux pas te donner la transposition.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 123
    Par défaut
    Salut Antoun,

    La solution que tu m'as proposé fonctionne bien. Toutefois, la jointure que je fais avec la tables de parité ouvrages_auteurs a pour effet de multiplier le résultat de la somme par le nombre d'auteurs. La seule solution que j'ai trouvé est de diviser le résultat de la somme par le nombre d'auteur mais je me doute qu'il y a une meilleure solution.

    De plus, sachant que nbreLivresActifs + nbreLivresInactifs = nbreLivres, crois-tu qu'il y a une manière de raccourcir ce code?

    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
    37
    38
    39
    SELECT
          O.idOuvrage,
          O.titre,
     
          GROUP_CONCAT(DISTINCT
             CONCAT_WS(' ', A.prenom, A.nom)
             ORDER BY A.nom
             SEPARATOR ', '
          ) AS listeAuteurs,
     
          COUNT(DISTINCT L.idLivre) AS nbreLivres,
     
          -- Livres invendus des vendeurs dont le compte est actif
          ROUND(SUM(
             CASE
                WHEN DATEDIFF(DATE_ADD(V.dateDerniereActivite, INTERVAL 2 YEAR), NOW()) >= 0
                THEN 1
                ELSE 0
             END
          )/COUNT(DISTINCT A.nom)) AS nbreLivresActifs,
     
          -- Livres invendus des vendeurs dont le compte est inactif
          ROUND(SUM(
             CASE
                WHEN DATEDIFF(DATE_ADD(V.dateDerniereActivite, INTERVAL 2 YEAR), NOW()) < 0
                THEN 1
                ELSE 0
             END
          )/COUNT(DISTINCT A.nom)) AS nbreLivresInactifs
     
       FROM ouvrages AS O
          LEFT JOIN livres AS L         ON O.idOuvrage = L.idOuvrage
          LEFT JOIN vendeurs AS V      ON L.idVendeur = V.idVendeur
          LEFT JOIN ouvrages_auteurs AS OA   ON O.idOuvrage = OA.idOuvrage
          INNER JOIN auteurs AS A         ON OA.idAuteur = A.idAuteur
     
       WHERE L.dateVente IS NULL
       GROUP BY O.idOuvrage
       ORDER BY O.titre

  4. #4
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 292
    Par défaut
    sans trop regarder ta requête, je te suggèrerais un truc comme ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    COUNT(DISTINCT CASE WHEN condition THEN IdLivre ELSE NULL END)

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    123
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 123
    Par défaut
    Merci Antoun!

    Ton apport sur ce forum est inestimable, merci encore un fois pour ton aide claire et efficace!

    J'ai utilisé le code suivant, et ça fonctionne très bien :

    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
    		-- Livres invendus des vendeurs dont le compte est actif
    		COUNT(DISTINCT
    			CASE
    			WHEN DATEDIFF(DATE_ADD(E.dateDerniereActivite, INTERVAL 2 YEAR), NOW()) >= 0
    			THEN L.idLivre
    			ELSE NULL
    			END
    		) AS nbreLivresActifs,
     
    		-- Livres invendus des vendeurs dont le compte est inactif
    		COUNT(DISTINCT
    			CASE
    			WHEN DATEDIFF(DATE_ADD(E.dateDerniereActivite, INTERVAL 2 YEAR), NOW()) < 0
    			THEN L.idLivre
    			ELSE NULL
    			END
    		) AS nbreLivresInactifs,
     
    		-- Livres invendus, au total (équivalent à « nbreLivresActifs + nbreLivresInactifs »)
    		COUNT(DISTINCT L.idLivre) AS nbreLivres

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 15/10/2007, 14h35
  2. Etat avec deux sources différentes
    Par Pigwi dans le forum VBA Access
    Réponses: 4
    Dernier message: 07/06/2007, 09h43
  3. Datagrid et combobox avec deux datasource différents
    Par RaelRiaK dans le forum VB.NET
    Réponses: 9
    Dernier message: 07/02/2007, 09h20
  4. Ecrire dans une CEdit avec deux Couleurs Différentes
    Par yoyothebest dans le forum MFC
    Réponses: 1
    Dernier message: 25/03/2006, 19h09
  5. Réponses: 8
    Dernier message: 13/03/2006, 17h37

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