Partage
  • Partager sur Facebook
  • Partager sur Twitter

requete mysql compliquée...

...pour moi en tous cas

Sujet résolu
    17 décembre 2010 à 19:08:26

    Bonjour,

    J'ai deux tables: clients, factures
    Dans la table clients, j'ai l'id des clients
    Dans la table factures, j'ai la date d'échéance de chaque facture + l'id des clients concernés,

    Je veux lister TOUS mes clients (même ceux qui ne sont pas référencés sur une facture)
    Jusque là, tout va bien, un simple "SELECT * FROM clients" fait l'affaire

    Par contre, je veux vérifier que, pour chaque client, s'il y a une ou plusieurs factures associées, aucune n'a une date d'échéance dépassée.
    Là, je coince total sur la requete.
    De plus, si je fais une requete en boucle pour lister les clients et une requete par client pour vérifier s'il a un retard sur une facture, ça fait beaucoup de requêtes au final.
    Y'a-t-il moyen de faire une requete qui me sort tout?

    Pour illustrer ma demande, voilà ce que j'aimerais afficher comme listing client si j'ai 5 clients et 20 factures en tout (dont 6 factures en retard de payement par les clients 1,3, et 4):

    client 1 (facturé - au moins un retard!)
    Client 2 (facturé - Aucun retard)
    Client 3 (facturé - au moins un retard!)
    Client 4 (facturé - au moins un retard!)
    Client 5 (jamais facturé )

    Merci pour votre aide

    • Partager sur Facebook
    • Partager sur Twitter
      17 décembre 2010 à 19:10:38

      Un petit début de de code pour nous aider ??
      • Partager sur Facebook
      • Partager sur Twitter
        17 décembre 2010 à 19:15:53

        moi en tout cas j'aurais fait comme tu as dit avec une boucle et un switch
        • Partager sur Facebook
        • Partager sur Twitter
          17 décembre 2010 à 19:18:29

          Je n'ai pas marqué de code car tout ce que j'ai tenté pue les pieds mais j'ai cherché!
          Voici un exemple de requete qui craint...

          "SELECT client_id, facture_echeance FROM clients AS c, factures AS f WHERE f.client_id= c.id_client UNION select id_client FROM clients GROUP BY c.id_client"


          ...en pensant naïvement que la première partie me sortirait les clients facturés avec leurs échéances,la seconde, tous les clients (donc aussi ceux sans factures) et que le GROUP BY me sortirait un ligne unique par client.

          Ca ne fonctionne évidemment pas.
          De plus, la requete groupe les clients pour ne pas avoir une ligne par facture mais si les clients sont groupés, les échéances de chaque facture seront écrasées, ce qui ne m'avance pas...
          Sue ce coup, je pense très mal et je le sais mais je ne vois pas comment faire.

          Comme tu vois, j'ai essayé, mais bof...
          A savoir que je ne cherche pas d'aide pour le script php en soi, ça je peux le faire. Juste la requete qui va bien et qui me permettrait de récupérer les données nécessaires pour coder le php trankilou.

          Merci pour l'aide!

          @lecodeurphp: ça je peux le faire mais t'imagines, si t'as 100 clients (ce qui est peu), ça te fait 101 requêtes pour une simple page d'affichage! C'est un coup à te mettre ton serveur sur les genoux...je crois.
          • Partager sur Facebook
          • Partager sur Twitter
            18 décembre 2010 à 3:03:58

            Je n'ai pas très bien compris ce que tu veut faire. Un peu compliqué tout sa mais je ne voie pas du tout comment faire là.
            • Partager sur Facebook
            • Partager sur Twitter
              18 décembre 2010 à 3:11:29

              En gros, je veux juste un listing de tous mes clients.
              MAIS je veux que ce listing marque en rouge les clients qui ont une facture impayée (c'est effectivement le cas si une de leur facture au moins a une date d'échéance qui est antérieure à la date du jour) sans forcément préciser laquelle, ce n'est pas nécessaire.
              Pour cela je dois parcourir la table facture pour récupérer la date d'échance du client ainsi que le client associé.
              Mais comme il existe aussi des clients qui n'ont pas de factures, je dois parcourir également la table clients qui contient TOUS les clients.
              Et puis..mixer le tout et récupérer les infos pour afficher mon listing client et afficher en rouge les mauvais payeurs éventuels...

              j'aimerais afficher ceci si j'ai 5 clients et 20 factures en tout (dont 6 factures en retard de payement par les clients 1,3, et 4): par exemple:
              5 clients et 20 factures en tout (dont 6 factures en retard de payement par les clients 1,3, et 4):

              client 1 (facturé - au moins un retard!)
              Client 2 (facturé - Aucun retard)
              Client 3 (facturé - au moins un retard!)
              Client 4 (facturé - au moins un retard!)

              Client 5 (pas de facture et donc aucun retard)

              • Partager sur Facebook
              • Partager sur Twitter
                18 décembre 2010 à 3:13:59

                Essaye :
                SELECT client_id, facture_echeance, facture_id FROM clients AS c, factures AS f
                

                Ensuite tu fait une boucle avec un if qui vérifie que client_id et facture_id sont identique pour ensuite affiché facture echeance. Un truc dans le genre ^^ (j'ai pas trouvé autre chose désoler)
                • Partager sur Facebook
                • Partager sur Twitter
                  18 décembre 2010 à 3:14:54

                  C'est bon mais par contre je ne verrai pas le "client 5" dans la liste, je me trompe?
                  (Pas grave Natsu Nakatomi, déjà sympa d'avoir essayé. Merci!)
                  • Partager sur Facebook
                  • Partager sur Twitter
                    18 décembre 2010 à 3:19:57

                    Si il n'a pas de facture, tu ne le verra pas donc, ce qui faudrait faire c'est crée une facture vide pour tout les clients, juste pour qu'il soie dans la liste au moins.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      18 décembre 2010 à 3:23:10

                      Arf, c'est un peu sale comme méthode.
                      D'autant plus que j'ai un listing client et que je ne me sert pas vraiment de la table client pour ma recherche, c'est bizarre!
                      Je pensais qu'une jointure de table pourrais faire l'affaire mais apparemment non...
                      Je pensais que ceci pouvait se faire en sql:

                      Citation : Moi

                      "Je veux tous les clients de la table client et pour ceux qui sont référencés dans la table facture, je veux, en prime, toutes les échéances associées."



                      Mais c'est vrai que la facture vide est une idée qui peut fonctionner...
                      Je vais voir.
                      • Partager sur Facebook
                      • Partager sur Twitter
                        18 décembre 2010 à 3:31:10

                        Sinon pour ne pas faire une facture vide, tu peut faire une requête qui vérifié si l'id d'un client n'a aucune facture associé et l'affiché avec les autres, sa serait l'histoire de rajouter quelque condition au if et une requête mysql de plus.
                        • Partager sur Facebook
                        • Partager sur Twitter
                          18 décembre 2010 à 3:34:34

                          Oui, je pensais effectivement à ça.
                          Pour un tri ultérieur éventuel des données, faudra que je passe par des tableaux en php alors...
                          Merci pour ton aide!
                          • Partager sur Facebook
                          • Partager sur Twitter
                            18 décembre 2010 à 4:56:39

                            Je crois que tu cherches un truc dans le genre :
                            --
                                     SELECT id_client, is_late
                                       FROM client c
                            LEFT OUTER JOIN (SELECT id_client, (MAX(date_echeance) > NOW()) AS is_late
                                             FROM factures
                                             GROUP BY id_client) f
                                         USING (id_client);
                            

                            is_late est un "booléen" qui contient True s'il y a au moins un retard, false s'il n'y en a pas et NULL s'il n'y a pas de factures pour un client.

                            D'ailleurs, j'imagine que tu dois vider ta table factures, sinon je ne vois pas comment tu peux savoir qu'une facture est en retard ou pas.

                            De plus, la question a plutôt sa place dans le forum Base de données, je déplace.
                            • Partager sur Facebook
                            • Partager sur Twitter
                              18 décembre 2010 à 8:42:43

                              Variantes :

                              1) utilisant le GROUP BY foireux de MYSQL
                              SELECT id_client, count(f.facture_id) as factures_en_retard
                                   FROM client c
                              LEFT JOIN factures f ON (c.id_client=f.id_client AND f.date_echeance < NOW())
                              GROUP BY id_client;
                              


                              2) SQL normal
                              SELECT c.*, n_late
                                   FROM client c
                              LEFT JOIN (
                                  SELECT id_client, count(*) AS n_late
                                  FROM factures
                                  WHERE date_echeance < NOW()
                                  GROUP BY id_client
                              ) f USING (id_client);
                              


                              Il me semble que la condition pour être en retard est date_echeance < NOW()...
                              • Partager sur Facebook
                              • Partager sur Twitter
                                18 décembre 2010 à 10:49:11

                                Rhoo ça a l'air bien ça!
                                J'essaye, merci Fayden et Lord Casque Noir!
                                (@ Fayden: en effet, je teste le retard en comparant simplement la date d'aujourd'hui et la date d'échéance.)

                                Edit:

                                Ca marche!!

                                En utilisant le code avec le "GROUP BY foireux de MYSQL" de Lord Casque Noir, j'obtiens un résultat (les autres requêtes semblent ne rien donner).

                                En effet, en faisant ceci:

                                <?php
                                mysql_connect($host, $login,$password);
                                mysql_select_db($db);
                                $sql=
                                  "SELECT id_client,client_denomination, count(f.id_facture) as factures_en_retard 
                                   FROM clients c 
                                   LEFT JOIN factures f 
                                   ON (c.id_client=f.client_id AND f.facture_date_echeance < NOW() AND f.facture_statut = 2) 
                                   GROUP BY id_client ";
                                
                                $requete = mysql_query($sql);
                                
                                while ($resultat= mysql_fetch_array($requete))
                                {
                                   echo $resultat['client_denomination']." (".$resultat['factures_en_retard'].") <br/>";
                                };
                                ?>
                                


                                j'obtiens ceci qui correspond bien à ma liste intégrale de clients, facturés ou non, suivi du nombre de retards (hourra):

                                Citation : moi

                                client 1 (2)
                                client 2 (0)
                                client 3 (2)
                                client 4 (1)
                                client 5 (0)


                                </span>


                                Merci à Fayden pour avoir solidement ouvert la voie et à Lord Casque Noir pour la note finale (et à tous les autres pour avoir essayé..après ça j'arrête, on se croirait à la remise des oscars...)!

                                PS: pourquoi qu'il est "foireux" le GROUP BY de MySQL?
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  18 décembre 2010 à 13:01:43

                                  Parce qu'une BDD normale te permet de faire :

                                  SELECT a,sum(d) GROUP BY a

                                  qui correspond à "pour chaque valeur de la colonne a, calculer la somme de la colonne d"

                                  et mysql te permet de faire :

                                  SELECT a,b,c,sum(d) GROUP BY a

                                  qui correspond en fait à "pour chaque valeur de la colonne a, calculer la somme de la colonne d, et retourner en prime les valeurs de b et d de n'importe quelle ligne (au hasard) parmi celles qui ont la valeur de a dont on parle"

                                  une BDD rigoureuse te pète une erreur du genre "je ne sais pas dans quelle ligne il faut prendre b et c donc je préfère ne rien faire plutôt que n'importe quoi" ; mysql (qui est joueur) préfère toujours faire n'importe quoi donc ça ne le gêne pas XD

                                  c'est fort pratique mais si on ne sait pas ce qu'on fait, ça retourne vite n'importe quoi...

                                  dans ton cas "a" est la clé primaire de clients, b et c viennent de clients, donc ça marche.
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    18 décembre 2010 à 13:13:48

                                    Ok, j'ai compris :-)

                                    Merci pour tout Lord Casque Noir.
                                    Jusqu'ici je me focalisais sur le code php en déconsidérant totalement les requêtes à la base, les réduisant à leurs plus simples expressions pour faire toute ma cuisine en php mais franchement, c'est étonnamment puissant.
                                    J'ai compris ta requête mais ne suis pas certain d'être capable d'en pondre une aussi poussée par moi-même.
                                    Pourtant, je suis certain que ça reste d'un niveau encore très léger...
                                    Va falloir que je m'y mette car ça ouvre des perspectives mais il faut dire qu'au premier abord, c'est assez déroutant.

                                    Très instructif en tous cas et l'explication du GROUP BY est clairement la cerise sur le gâteau.

                                    Merci encore!
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      18 décembre 2010 à 14:34:15

                                      > qui correspond en fait à "pour chaque valeur de la colonne a, calculer la somme de la colonne d"

                                      il doit manquer une virgule ou autre, affiche les erreurs de tes requêtes (or die ...)

                                      Citation : sasquatch

                                      Jusqu'ici je me focalisais sur le code php en déconsidérant totalement les requêtes à la base, les réduisant à leurs plus simples expressions pour faire toute ma cuisine en php mais franchement, c'est étonnamment puissant.



                                      En fait il faut faire l'inverse : si tu flingues ta BDD, ton site va ramer (ou avoir l'angoisse de la page blanche)... on commence toujours par la conception de la BDD, après le php c'est accessoire, tu peux toujours le changer, tandis que reprendre une BDD mal foutue c'est la mort, faut changer toutes les requêtes, etc.

                                      Mettons que tu as un site moyen avec une BDD de 1 Go, toute tentative de faire un gros traitement autrement qu'en SQL c'est l'échec assuré XD
                                      • Partager sur Facebook
                                      • Partager sur Twitter

                                      requete mysql compliquée...

                                      × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                      × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                      • Editeur
                                      • Markdown