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

PHP & Base de données Discussion :

Affiner une requête avec jointure [MySQL]


Sujet :

PHP & Base de données

  1. #1
    Candidat au Club
    Homme Profil pro
    Intégrateur Web
    Inscrit en
    août 2019
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Intégrateur Web

    Informations forums :
    Inscription : août 2019
    Messages : 2
    Points : 3
    Points
    3
    Par défaut Affiner une requête avec jointure
    Bonjour,

    J'ai 2 tables, clients et commandes.

    J'ai fait une requête qui m'affiche la listes des clients ainsi que le nombre total de commandes passés par chaque client et la somme totale des commandes.

    Voici la requête en question:

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT c.id_customer, c.firstname, c.lastname, c.email, c.register_date, o.current_state, 
    COUNT(o.id_customer) AS sales, SUM(o.total_amout) AS total_sales
    FROM customer c 
    LEFT JOIN orders o
    ON o.id_customer = c.id_customer
    GROUP BY c.id_customer
    ORDER BY c.register_date DESC

    (N'hésitez pas à me faire part de vos remarques/conseils si vous pensez que ma requête est complètement naze et/ou qu'on peut vraiment l'optimiser)

    Cette requête fonctionne seulement j'aimerais maintenant pouvoir ne comptabiliser que les commandes (et le total de celles-ci) qui ont un statut spécifique (à la deuxième ligne) grâce à la colonne order.current_state.

    C'est-à-dire ne comptabiliser que les commandes qui ont bien été livrés et qui n'ont pas été annulés/remboursés par exemple (ex. WHERE order.current_state = 3).

    Merci d'avance!


    EDIT

    Je pense avoir trouvé une solution avec "CASE" que je ne connaissais pas.

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT c.id_customer, c.firstname, c.lastname, c.email, c.register_date, o.current_state, 
    COUNT(case when o.current_state = 3 then o.id_customer else NULL end) AS sales, SUM(case when o.current_state = 3 then o.total_amout else 0 end) AS total_sales
    FROM customer c 
    LEFT JOIN orders o
    ON o.id_customer = c.id_customer
    GROUP BY c.id_customer
    ORDER BY c.register_date DESC

    Je vais donc marquer le sujet comme résolu.

    Ceci dit, si vous pensez que ma requête est trop complexe pour le résultat souhaité et que l'on peut vraiment l'optimiser je suis également toujours preneur!

  2. #2
    Membre chevronné Avatar de Toufik83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    janvier 2012
    Messages
    1 203
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : janvier 2012
    Messages : 1 203
    Points : 2 001
    Points
    2 001
    Par défaut
    Salut,

    Je pense que ma réponse vient un peu trop tard mais je voudrais comprendre pourquoi ne pas utiliser inner join au lieu de left join, et pourquoi case au lieu d'un simple where ?

    Parce que avec inner join, tu élimines les clients qui n'ont effectués aucune commande, après tu utilises where pour ne sélectionner que les clients qui ont effectués au moins une commande ayant le current_state = 3.
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    SELECT c.id_customer, c.firstname, c.lastname, c.email, c.register_date, o.current_state, 
    COUNT(o.id_customer) AS sales, SUM(o.total_amout) AS total_sales
    FROM customer c 
    INNER JOIN orders o
    ON o.id_customer = c.id_customer
    WHERE o.current_state=3
    GROUP BY c.id_customer
    ORDER BY c.register_date DESC

    Une autre remarque concernant le count(o.id_customer) : Normalement la table orders doit avoir une clé primaire et en auto-incrémente, et c'est cette clé que tu dois compter parce qu'elle représente une commande.

  3. #3
    Rédacteur/Modérateur
    Avatar de jreaux62
    Homme Profil pro
    Webdesigner
    Inscrit en
    août 2008
    Messages
    16 032
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Webdesigner
    Secteur : Arts - Culture

    Informations forums :
    Inscription : août 2008
    Messages : 16 032
    Points : 32 837
    Points
    32 837
    Par défaut
    Bonjour,

    Citation Envoyé par Toufik83 Voir le message
    ...avec inner join, tu élimines les clients qui n'ont effectués aucune commande...
    @Toufik83
    Justement !
    Il faut utiliser LEFT JOIN pour afficher AUSSI les clients qui n'ont pas de commandes !

    D'autre part, au lieu du WHERE, je mettrais un AND dans le ON :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    SELECT 
      c.id_customer, c.firstname, c.lastname, c.email, c.register_date, 
      o.current_state, 
      COUNT(o.*) AS sales, 
      SUM(o.total_amout) AS total_sales
    FROM customer c 
    LEFT JOIN orders o
      ON (o.id_customer = c.id_customer AND o.current_state=3)
    GROUP BY c.id_customer
    ORDER BY c.register_date DESC

    A tester...
    "Si tu suis le chemin qui s'appelle « plus tard », tu arriveras à la place qui s'appelle « jamais »."
    François Camille Prévot (1910-1996), instituteur puis Directeur d'école et... mon grand-père.
    "Pose ta question, tu seras idiot une seconde. Ne la pose pas, tu seras idiot toute ta vie."
    Albert Einstein (1879-1955).
    Mes tutos DVP
    Gestion-Affichage de Nouvelles
    Affichage en tableau HTML
    Fonctions de redimensionnement d'images

  4. #4
    Candidat au Club
    Homme Profil pro
    Intégrateur Web
    Inscrit en
    août 2019
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Intégrateur Web

    Informations forums :
    Inscription : août 2019
    Messages : 2
    Points : 3
    Points
    3
    Par défaut
    Bonjour à vous deux!

    En effet comme l'a dit jreaux62 je souhaite afficher tous les clients, même ceux qui n'ont rien commandé. (ça n'était peut-être en effet pas très clair dans mon post initial)

    Citation Envoyé par Toufik83
    Une autre remarque concernant le count(o.id_customer) : Normalement la table orders doit avoir une clé primaire et en auto-incrémente, et c'est cette clé que tu dois compter parce qu'elle représente une commande.
    Très juste! Merci!


    J'étais persuadé d'avoir testé ta solution jreaux62 puis j'ai abandonné à cause d'une erreur dont je ne me souviens plus.

    Alors qu'en fait ça fonctionne très bien, c'est plus simple et surtout bien plus "logique".

    Ça m'aura tout de même permis de connaître l'expression "CASE".

    Merci à vous deux pour votre aide! Super Forum!

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

Discussions similaires

  1. Aide sur une requête avec jointure..
    Par WeDgEMasTeR dans le forum Requêtes
    Réponses: 7
    Dernier message: 10/11/2009, 19h09
  2. Réponses: 11
    Dernier message: 15/09/2008, 11h25
  3. Lenteur sur une requête avec jointure
    Par mister3957 dans le forum SQL
    Réponses: 16
    Dernier message: 13/08/2008, 14h10
  4. [ABAP] Comment créer une requête avec jointure
    Par roadster62 dans le forum SAP
    Réponses: 1
    Dernier message: 21/02/2006, 17h04
  5. optimisation d'une requête avec jointure
    Par champijulie dans le forum PostgreSQL
    Réponses: 8
    Dernier message: 07/07/2005, 10h45

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