Jump to content

Besoin d'aide sur une requete SQL


Recommended Posts

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 Y
dont 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 B)... (selon ce que j'ai besoin)

Voilà ! Quelqu'un peut-il m'aider ??

Merci d'avance

Link to comment
Share on other sites

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

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

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

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

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

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

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

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

ç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

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

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

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

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

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

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

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

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

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

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

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...