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


Sujet :

PHP & Base de données

  1. #1
    Candidat au Club
    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 émérite
    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
    Invité
    Invité(e)
    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...

  4. #4
    Candidat au Club
    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!

###raw>template_hook.ano_emploi###