Odjavel Posted March 28, 2011 Share Posted March 28, 2011 Bonjour,Je suis en train de faire mon premier module Prestashop, et j'en ch... un max ! ;-) C'est un module pour un transporteur.Malgré mes compétences moyennes en PHP, je suis arrivé à tout développer.Je bute cependant sur une chose : la requete SQL de base pour que mon module fonctionne.J'y comprends rien aux JOIN et LEFT JOIN etc. Je vous jure que j'ai essayé, mais ça me rend fou !Donc, j'aurais besoin qu'un pro de la prog puisse m'aider à faire cette requête SQL.Je dois rechercher :Nom + Prénom + Société + adresse de livraison (avec les commentaires libres)correspondants à toutes les commandes passées entre la date X et la date Ydont le statut de commande (id_order_state) est 1 ou 2 ou (1 et 2)... (selon ce que j'ai besoin)et dont le transporteur est A ou B ou (A et ... (selon ce que j'ai besoin)Voilà ! Quelqu'un peut-il m'aider ??Merci d'avance Link to comment Share on other sites More sharing options...
Broceliande Posted March 28, 2011 Share Posted March 28, 2011 question idiote , tu es en 1.4 ou 1.3 ? Link to comment Share on other sites More sharing options...
jeckyl Posted March 28, 2011 Share Posted March 28, 2011 Salut,juste pour aider, le plus simple pour les join c'est de ne pas vraiment en faire. Je m'explique.Au lieu de faire de left join ou autre complexité à comprendre il suffit d'associer les tables entres elles sur une donnée identique.Ainsi, lorsque tu utilises 2 table pour les produits, en générale elles ont toutes les 2 l'id du produit alors ta requêtes est du style :SELECT * FROM tb1, tb2 WHERE tb1.id_product = tb2.id_product ainsi tu as associé les 2 tables et tu peux récupérer les donnes de chaque tables. Link to comment Share on other sites More sharing options...
Broceliande Posted March 28, 2011 Share Posted March 28, 2011 Sinon , sans aller contre la suggestion de jeckyl , une requete exemple , avec des joins SELECT o.id_carrier, o.id_order, o.id_address_delivery, ad.id_address, ad.company, ad.firstname, ad.lastname, ad.address1, ad.address2, ad.postcode, ad.city, oh.id_order, oh.id_order_state, o.date_add FROM ps_orders AS o LEFT JOIN ps_address AS ad ON ad.id_address = o.id_address_delivery LEFT JOIN ps_order_history AS oh ON oh.id_order = o.id_order WHERE o.date_add >= 'yyyy-mm-dd 00:00:00' AND o.date_add <= 'yyyy-mm-dd 29:59:59' AND oh.id_order_state = 2 Edit , je m'édite pour préciser que jeckyl a raison à 100% : sa methode est bien plus facile d'approche en terme de compréhension , mais avant de lire sa réponse , j'avait déja préparé ma requete ... elle est donc là Link to comment Share on other sites More sharing options...
Odjavel Posted March 28, 2011 Author Share Posted March 28, 2011 Je rentre à peine du bureau et je découvre vos réponses.Avant même de les comprendre, je tiens à vous remercier pour votre intéret et votre rapidité !Je m'y colle tout de suite pour voir si j'arrive à quelque chose.Pour répondre à ta question, Broceliande, je suis en 1.4 Link to comment Share on other sites More sharing options...
Broceliande Posted March 28, 2011 Share Posted March 28, 2011 Ca doit passer en 1.4, mais j'en ai oublié le transporteur... SELECT o.id_carrier, o.id_order, o.id_address_delivery, ad.id_address, ad.company, ad.firstname, ad.lastname, ad.address1, ad.address2, ad.postcode, ad.city, oh.id_order, oh.id_order_state, o.date_add, c.`name` FROM ps_orders AS o LEFT JOIN ps_address AS ad ON ad.id_address = o.id_address_delivery LEFT JOIN ps_order_history AS oh ON oh.id_order = o.id_order LEFT JOIN ps_carrier AS c ON c.id_carrier = o.id_carrier WHERE o.date_add >= 'yyyy-mm-dd 00:00:00' AND o.date_add <= 'yyyy-mm-dd 29:59:59' AND oh.id_order_state = 2 AND c.`name` = 'Nom Transporteur' Link to comment Share on other sites More sharing options...
jeckyl Posted March 28, 2011 Share Posted March 28, 2011 Edit , je m'édite pour préciser que jeckyl a raison à 100% : sa methode est bien plus facile d'approche en terme de compréhension , mais avant de lire sa réponse , j'avait déja préparé ma requete ... elle est donc là Merci, tu as tout à fait compris le principe de mon explication simplicité d'approche pour le plus grand nombre car les left join déstabilisant rapidement.Par contre je me demande si il y a une façon de faire qui augmenter la performance de la requête sur de gros volumes de données. Je me rappel pas avoir vu passer une étude sur ce point précis. Link to comment Share on other sites More sharing options...
Broceliande Posted March 28, 2011 Share Posted March 28, 2011 Tu as piqué ma curiosité J'aurais tendance à penser qu'un JOIN reste plus rapide, étant donné qu'avec la méthode plus logiquement compréhensible du t1.field = t2.field , la jonction est implicite.Il y a donc nécessairement un temps additionnel (peut être parfaitement négligeable au demeurant) de traitement de cette requête par le moteur.J'ai moi aussi débuté par ces reqûetes , et je dois avouer que j'ai galéré comme tout le monde avec les JOIN , mais le fait est qu'une fois assimilée, la methode join permet également de se moins se perdre , surtout quand on a un paquet de tables.Elle est je pense plus naturelle pour mysql , et le résultat est moins hasardeux parce qu'on a le contrôle de la jonction (LEFT INNER RIGHT) .Si tu veux un select distinct sur un champ , il me semble également moins m'y perdre que par le passé.En terme de performances , on pourrait s'amuser à mesurer , pour notre culture perso lol.Tu peux par exemple ecrire la meme requête que celle ci-dessus en écrituree simplifiée et on teste ça ?Pas sûr qu'on y trouve une différence notable sur une seule exécution.Je sais une chose par contre , c'est que le pire , avec mysql , c'est de faire un where ... IN (select * from ... ) , ce pour en avoir fais les frais. Link to comment Share on other sites More sharing options...
Odjavel Posted March 28, 2011 Author Share Posted March 28, 2011 Bon.J'ai testé la requete de Brocéliande.Rien que l'insertion de cette requete sur ma page, du type $sql='SELECT...ta requete...'; fait planter mon BO.Pour le moment, je n'ai pas vraiment compris pourquoi.Je vais chercher, et vais tenter aussi la méthode Jeckyl, pour voir. Link to comment Share on other sites More sharing options...
Broceliande Posted March 28, 2011 Share Posted March 28, 2011 Odjavel , je sais pourquoi : il manque un distinct , ma requête est trop large...Je vais revoir ma copie , entre deux, mais effectivement la methode de jeckyll est à tester. Link to comment Share on other sites More sharing options...
Broceliande Posted March 28, 2011 Share Posted March 28, 2011 Revoilà un exemple filtré qui marche ici (valeurs à adapter pour toi bien sûr ) SELECT DISTINCT o.id_carrier, o.id_order, o.id_address_delivery, ad.id_address, ad.company, ad.firstname, ad.lastname, ad.address1, ad.address2, ad.postcode, ad.city, oh.id_order, oh.id_order_state, o.date_add, c.`name` FROM ps_orders AS o INNER JOIN ps_address AS ad ON ad.id_address = o.id_address_delivery INNER JOIN ps_order_history AS oh ON oh.id_order = o.id_order INNER JOIN ps_carrier AS c ON c.id_carrier = o.id_carrier , ps_order_history WHERE o.date_add >= '2010-12-01 00:00:00' AND o.date_add <= '2010-12-31 23:59:59' AND oh.id_order_state = 2 GROUP BY o.id_order Link to comment Share on other sites More sharing options...
Odjavel Posted March 28, 2011 Author Share Posted March 28, 2011 ça y est j'ai trouvé. J'avais un conflit d’apostrophes. Mon BO ne plante plus, mais c'est pas gagné pour autant.J'en suis à la phase "ma requete marche-t-elle ?"J'ai donc ce code : $sql='SELECT...la requete de broceliande...'; $req = Db::GetInstance()->getRow($sql); while($data = mysql_fetch_array($req)) { $a = $data['firstname']; echo $a; } La page s'affiche, mais aucun prénom.J'ai encore un peu de mal avec les instructions liées à sql. Autodidacte, c'est chaud, passé la trentaine... :sick:EDIT : j'ai testé avec ta derniere requete, mais c'est pareil. Autre chose, je me suis aussi assuré que les éléments que je demande existent. J'ai mis l'ID des commandes expédiées sur un jour en janvier. Donc, c'est sur, il y a des réponses. Link to comment Share on other sites More sharing options...
jeckyl Posted March 28, 2011 Share Posted March 28, 2011 Surtout ton gros problème c'est que Prestashop est en POO (Programmation Orienté Objet) et que donc il faut apprendre à maitriser un certains nombre de choses nouvelles seulement pour Prestashop, comme par exemple récupérer les données d'une requête.Regarde sur d'autres modules pour comprendre. Link to comment Share on other sites More sharing options...
Odjavel Posted March 28, 2011 Author Share Posted March 28, 2011 Jusqu'à présent, j'avais pas eu besoin de faire des requetes pour les modifs que j'ai fait sur mon shop. Donc je les redécouvre un peu.J'ai intégré le concept de l'orienté objet, même si je ne le maitrise pas comme je voudrais, mais je passe encore a coté de certaines choses comme celle-là. Je vais chercher.En tout cas merci encore pour vos réponses ! Link to comment Share on other sites More sharing options...
Broceliande Posted March 28, 2011 Share Posted March 28, 2011 pour ce qui est de la méthode indiquée par jeckyl , en voici un exemple : SELECT DISTINCT c.id_carrier, o.id_order, o.id_address_delivery, ad.id_address, ad.company, ad.firstname, ad.lastname, ad.address1, ad.address2, ad.postcode, ad.city, oh.id_order, oh.id_order_state, o.date_add, c.name FROM ps_orders AS o , ps_address AS ad , ps_order_history AS oh , ps_carrier AS c WHERE ad.id_address = o.id_address_delivery AND oh.id_order = o.id_order AND c.id_carrier = o.id_carrier AND o.date_add >= '2010-01-01 00:00:00' AND o.date_add <= '2011-12-31 23:59:59' AND oh.id_order_state = 2 AND c.name like '%La Poste%' GROUP BY o.id_order J'ai testé les deux méthodes et le résultat est sans appel : celle de jeckyl prends bien moins de temps !Je me suis donc planté en présumant que mysql préférait les 'join'.Pour info , et surtout pour jeckyl , la requête suivante , équivalente à celle ci-dessus mais en join , met plus de 4 secondes contre 0,044 ms ... mazette , je me demande comment presta fait pour être aussi rapide. : SELECT DISTINCT o.id_carrier, o.id_order, o.id_address_delivery, ad.id_address, ad.company, ad.firstname, ad.lastname, ad.address1, ad.address2, ad.postcode, ad.city, oh.id_order, oh.id_order_state, o.date_add, c.`name` FROM ps_orders AS o INNER JOIN ps_address AS ad ON ad.id_address = o.id_address_delivery INNER JOIN ps_order_history AS oh ON oh.id_order = o.id_order INNER JOIN ps_carrier AS c ON c.id_carrier = o.id_carrier , ps_order_history WHERE o.date_add >= '2010-01-01 00:00:00' AND o.date_add <= '2011-12-31 23:59:59' AND oh.id_order_state = 2 AND c.name like '%La Poste%' GROUP BY o.id_order Link to comment Share on other sites More sharing options...
jeckyl Posted March 28, 2011 Share Posted March 28, 2011 Merci pour ce retour d'expérience st surtout un résultat probant donc pour que je fasse jamais l'effort d'apprendre à maitriser les join ;-)Comme quoi des dev à l'ancienne cela permets bien des optimisations des fois.C'est comme faire des requête au lieu de créer des objets, cela est plus performant. Mais bon dans ce cas il faut vraiment être obligé car c'est beaucoup plus complexe à traiter. Link to comment Share on other sites More sharing options...
Broceliande Posted March 28, 2011 Share Posted March 28, 2011 Odjavel, je pense que tu devrais plûtot utiliser un truc du genre : $sql='SELECT...la requete façon table.champ cette fois, mais ça change rien aux résultats....'; $result= Db::GetInstance()->ExecuteS($sql); foreach($result as $row) { echo $row['firstname']; } Link to comment Share on other sites More sharing options...
Broceliande Posted March 28, 2011 Share Posted March 28, 2011 Merci pour ce retour d'expérience st surtout un résultat probant donc pour que je fasse jamais l'effort d'apprendre à maitriser les join ;-)Comme quoi des dev à l'ancienne cela permets bien des optimisations des fois.C'est comme faire des requête au lieu de créer des objets, cela est plus performant. Mais bon dans ce cas il faut vraiment être obligé car c'est beaucoup plus complexe à traiter. Tout à fait d'accord pour les requêtes, en terme de performances, mais bien au delà de la complexité, il faut penser qu'en objet , un module restera compatible tant que les propriétés de l'objet existent, même si la table , elle , change.C'est comme la refactorisation systématique du code... On ne pensait pas comme ça quand on codait avec mes potes sur msx, atari st etc... Seulement la portabilité n'avait que peu de sens , ce qui n'est plus le cas aujourd'hui. Désormais c'est même le maître mot...portabilité Link to comment Share on other sites More sharing options...
jeckyl Posted March 28, 2011 Share Posted March 28, 2011 Merci pour ce retour d'expérience st surtout un résultat probant donc pour que je fasse jamais l'effort d'apprendre à maitriser les join ;-)Comme quoi des dev à l'ancienne cela permets bien des optimisations des fois.C'est comme faire des requête au lieu de créer des objets, cela est plus performant. Mais bon dans ce cas il faut vraiment être obligé car c'est beaucoup plus complexe à traiter. Tout à fait d'accord pour les requêtes, en terme de performances, mais bien au delà de la complexité, il faut penser qu'en objet , un module restera compatible tant que les propriétés de l'objet existent, même si la table , elle , change.C'est comme la refactorisation systématique du code... On ne pensait pas comme ça quand on codait avec mes potes sur msx, atari st etc... Seulement la portabilité n'avait que peu de sens , ce qui n'est plus le cas aujourd'hui. Désormais c'est même le maître mot...portabilité c'est bien ce que je dit, obligation fait loi sinon on code proprement pour la pérennité du produit ou du projet. Dans mon cas j'ai dû abandonner les objets dans mon module d'export Google shopping car lorsque l'on dépasse les 5 000 produit les boucles sur des objets explosent les serveurs. Link to comment Share on other sites More sharing options...
Odjavel Posted March 28, 2011 Author Share Posted March 28, 2011 Odjavel, je pense que tu devrais plûtot utiliser un truc du genre :$sql='SELECT...la requete façon table.champ cette fois, mais ça change rien aux résultats....'; $result= Db::GetInstance()->ExecuteS($sql); foreach($result as $row) { echo $row['firstname']; } Effectivement, ça marche beaucoup mieux ! Encore merci, c'est vraiment sympa !Et je suis aussi très très fier d'être à l'origine d'un débat aussi passionnant à propos du gros manque de vivacité que peut provoquer un JOIN. (facile) Link to comment Share on other sites More sharing options...
Broceliande Posted March 28, 2011 Share Posted March 28, 2011 c’est bien ce que je dit, obligation fait loi sinon on code proprement pour la pérennité du produit ou du projet. Dans mon cas j’ai dû abandonner les objets dans mon module d’export Google shopping car lorsque l’on dépasse les 5 000 produit les boucles sur des objets explosent les serveurs. On se comprends bien . On pourrait exploser le thread si on continue lol.Pour quand un canal irc officiel pour développeurs presta?Il existe peut être mais jamais entendu parler...Hmpf je barre totalement hors-sujet ... pardon messieurs les moderos , c'est la faute au Dr Jeckyl ! Link to comment Share on other sites More sharing options...
Broceliande Posted March 28, 2011 Share Posted March 28, 2011 Effectivement, ça marche beaucoup mieux ! Encore merci, c’est vraiment sympa !Et je suis aussi très très fier d‘être à l’origine d’un débat aussi passionnant à propos du gros manque de vivacité que peut provoquer un JOIN. (facile) Content que ça prenne tournure Pour le débat il me semble bien que tu aies failli en lancer un autre ... n'avons nous pas débattu in an english way récemment ? Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now