Aller au contenu

Optimiser cette requête Mysql


steph13

Sujets conseillés

Bonjour le Hub,

Ennoncé:

Je souhaite mettre à disposition des visiteurs un formulaire de recherche multicritères.

Les choix seront sous formes de cases à cocher.

Jusque la tout va bien... D

Le formulaire est donc envoyé vers une page php qui va le traiter.

J'ai donc ecrit une requête Mysql qui va traiter les choix du visiteurs et lui retourner les infos contenue dans la bdd en fonctions de sa demande.

Hors, si ma requête fonctionne, je ne suis pas certain du tout qu'elle soit optimisée.

Je vous livre ici le code de la requête en question.



//choix de l'operateur
$operateur='and';

//les choix du visiteurs
//pour le moment en manuel,pour le besoin des tests;)
$mode='';
$publicite='Y';
$glamour='';
$lingerie='Y';
$topless='';
$nu='';
$charme='Y';
$erotique='';


//on crée la requete
$select = "SELECT * FROM mm_modele WHERE region='01' AND cat='modele' AND valide='Y' AND cache='non' AND (";
if ($mode!=''){$select.="mode='Y' ";}

if ($publicite!=''){
if ($mode!=''){
if ($operateur=='or'){$select.=" OR ";} else {$select.=" AND ";}}
$select.="publicite='Y' ";}

if ($glamour!=''){
//on teste systematiquement la valeur des varibales précédentes pour selectionner ou non l'opérateur >> ce qui ne me semble pas une bonne chose
if ($publicite!='' || $mode!=''){
if ($operateur=='or'){$select.=" OR ";} else {$select.=" AND ";}}
$select.="glamour='Y'";}

if ($lingerie!=''){
if ($publicite!='' || $mode!='' || $glamour!=''){
if ($operateur=='or'){$select.=" OR ";} else {$select.=" AND ";}}
$select.="lingerie='Y'";}

if ($topless!=''){
if ($publicite!='' || $mode!='' || $glamour!='' || $lingerie!=''){
if ($operateur=='or'){$select.=" OR ";} else {$select.=" AND ";}}
$select.="topless='Y'";}

if ($nu!=''){
if ($publicite!='' || $mode!='' || $glamour!='' || $lingerie!='' || $topless!=''){
if ($operateur=='or'){$select.=" OR ";} else {$select.=" AND ";}}
$select.="nu='Y'";}

if ($charme!=''){
if ($publicite!='' || $mode!='' || $glamour!='' || $lingerie!='' || $topless!='' || $nu!=''){
if ($operateur=='or'){$select.=" OR ";} else {$select.=" AND ";}}
$select.="charme='Y'";}

if ($erotique!=''){
if ($publicite!='' || $mode!='' || $glamour!='' || $lingerie!='' || $topless!='' || $nu!='' || $charme!=''){
if ($operateur=='or'){$select.=" OR ";} else {$select.=" AND ";}}
$select.="erotique='Y'";}


$select.= ") ORDER BY login ASC " or die(mysql_error());

Comme je le disais, la requête fonctionne bien.

Mais n'y a t-il pas une façon plus clean d'ecrire tout cela ?

Merci de votre aide.

Stef'

Lien vers le commentaire
Partager sur d’autres sites

Salut ;)

Ce qui est sûr, c'est que ce n'est pas optimisé non... Optimisé, c'est quand même la recherche de raccourcis, et toi là tu mets tout tout !

Enfin bon, vu le temps de réponse de ce genre de programme, vu que tu le fais qu'une fois, et que tu n'auras sûrement pas 50 inscriptions à la seconde, ça va pas tuer ton serveur...

Si tu veux optimiser un peu, ce que j'ai fait moi :

Dans mon formulaire HTML, j'ai mis comme nom choix-1, choix-2...

Ensuite, pour le traitement PHP, tu fais un tableau contenant les noms des colonnes

$nom_col = array('1'=>'publicité', '2'=>'glamour'  [...] );

Puis tu fais une petite boucle :

for ($i;$i<=$nb_de_choix;$i++)

Ensuite un petit if ($_POST[choix_$i] == 'y') $requete .= " AND ".$nom_col[$i]." = 'machin'";

Tu peux t'en sortir comme ça, et rajouter comme ça rapidement des choix dans ton tableau, sans te prendre la tête...

Enfin c'est une solution, je ne garantis pas que c'est la meilleure, mais c'est celle que j'ai opté ;)

Lien vers le commentaire
Partager sur d’autres sites

Salut Sarc,

Oui, en effet, c'est un peu le problème quand on a pas encore une totale maitrise de son outil, on a tendance à quelque peu s'étaler :P

Je vais tester de ce pas la solution que tu me soumet la.

Merci à toi d'avoir répondu si vite :)

Cependant, je reste preneur d'autre(s) technique(s). (Rien de tel pour se perfectionner encore et toujours...)

Modifié par steph13
Lien vers le commentaire
Partager sur d’autres sites

Bien...

Voila ou j'en suis:

$choix1='Y';
$choix2='Y';
$choix3='Y';

$nom_col=array('1'=>'mode', '2'=>'publicite', '3'=>'glamour');
//on crée la requete
$select = "SELECT * FROM mm_modele WHERE region='01' AND cat='modele' AND valide='Y' AND cache='non' AND (";

for ($i=0;$i<=$nb_de_choix;$i++) {
if ($choix[$i]=='Y'){ $select .= " AND ".$nom_col[$i]." = 'Y'";}}

$select.= ") ORDER BY login ASC " or die(mysql_error());

Sauf que je coince, car cela ne fonctionne pas....

La boucle for ne me renvoi rien du tout.

Et j'avoue avoir un mal de chien à maitriser ce type de boucle encore.

Merci de votre aide

Stef'

Modifié par steph13
Lien vers le commentaire
Partager sur d’autres sites

$choix1='Y';
$choix2='Y';
$choix3='Y';

Tu t'es trompé dans la définition du tableau $choix.

Fait comme ceci :

$choix[]='Y';
$choix[]='Y';
$choix[]='Y';

A voir aussi, si tu commence ta boucle avec $i=0, il faut que ton tableau $nom_col=array('1'=>'mode', '2'=>'publicite', '3'=>'glamour'); commence à 0 : $nom_col=array('0'=>'mode', '1'=>'publicite', '2'=>'glamour'); Ou alors il faut que tu commence ta boucle à $i=1.

Lien vers le commentaire
Partager sur d’autres sites

Troisième chose, il faut que tu mettes une valeur à $nb_de_choix, ou en l'occurence tu peux mettre $nb_de_choix = count($nom_col);

Lien vers le commentaire
Partager sur d’autres sites

De plus, et à moins d'être sur d'avoir au moins 1 choix qui passera dans ta boucle de condition, tu ne devrais pas écrire cela:

//on crée la requete
$select = "SELECT * FROM mm_modele WHERE region='01' AND cat='modele' AND valide='Y' AND cache='non' AND (";

mais t'habituer à écrire ceci

//on crée la requete
$select = "SELECT * FROM mm_modele WHERE region='01' AND cat='modele' AND valide='Y' AND cache='non' ";

Histoire de te dire que si aucun choix n'est validé par ta boucle de condition, alors tu termines par ton ORDER BY...

xpatval

Lien vers le commentaire
Partager sur d’autres sites

Yes...

Bon, je vais dejeuner dehors, histoire de rpeser mon neurone.

En revenant, je fais la synthèse de toutes vos infos.

Et je vous tiens au courant.

Merci de votre aide à tous.

Stef', qui va bien finir par s'en sortir :)

Lien vers le commentaire
Partager sur d’autres sites

Bien !

Et bah voila :)

Avec tout ça, j'y suis arrivé !!

Et y'a pas, ecrit comme il faut, c'est quand plus court et plus mieux :D

Merci à vous tous.

Stef'

Lien vers le commentaire
Partager sur d’autres sites

Tant mieux si ça marche bien alors ;)

Par contre laisse ton code sur le topic si tu veux bien, au moins si des gens ont besoin de faire la même chose, ils pourront s'en inspirer !

Lien vers le commentaire
Partager sur d’autres sites

Bon...En fait, non, ca ne fonctionne pas comme ma requête d'origine...

Je viens de faire plusieurs tests sur différentes requêtes, et les résultats sont différents.

J'explique le pourquoi du comment dans un prochain post.

Modifié par steph13
Lien vers le commentaire
Partager sur d’autres sites

Alors, ma première requête, non optimisé me donne ceci :

$select=SELECT * FROM mm_modele WHERE region='01' AND cat='modele' AND valide='Y' AND cache='non' AND (publicite='Y' OR lingerie='Y' OR charme='Y') ORDER BY login ASC

Et la requête modifié me donne:

$select=SELECT * FROM mm_modele WHERE region='01' AND cat='modele' AND cache='non' OR publicite = 'Y' OR lingerie = 'Y' OR charme = 'Y'ORDER BY login ASC

De fait,sur la seconde, ça me sort pratiquement tout ce qu'il y a dans la table.

La différence se fait ici :

Sur la première requête j'ai : (publicite='Y' OR lingerie='Y' OR charme='Y')

le tri se fait donc bien, les paramètres avant les prenthèse sont bien pris en compte. (region, valide, cache)

Sur la seconde j'ai :

OR publicite = 'Y' OR lingerie = 'Y' OR charme = 'Y'

Le fait de plus avoir de prenthèse me met le bazard, et de plus, le tri n'est plus bon du tout... Les critères region, cache et valide ne sont plus vraiment pris en compte.

Precision:

Ce que je veux faire en "bon francais":

Selectionner tous les enregistrements de la region XX, qui sont valides et non cachés ET dont valeur1=y et/ou valeur2=Y et/valeurX=Y

Je continue de chercher de mon cote, mais si vous avez une idée, c'est bienvenue.

Modifié par steph13
Lien vers le commentaire
Partager sur d’autres sites

Voila un code qui donne tout bien comme il faut :


$operateur=$_POST['operateur'];
$region=$_POST['region'];

$choix = array();
if (isset($_POST['choix0']))
$choix[] = "mode = 'Y'";
if (isset($_POST['choix1']))
$choix[] = "publicite = 'Y'";
if (isset($_POST['choix2']))
$choix[] = "glamour = 'Y'";
if (isset($_POST['choix3']))
$choix[] = "lingerie = 'Y'";
if (isset($_POST['choix4']))
$choix[] = "topless = 'Y'";
if (isset($_POST['choix5']))
$choix[] = "nu = 'Y'";
if (isset($_POST['choix6']))
$choix[] = "charme = 'Y'";
if (isset($_POST['choix7']))
$choix[] = "erotique = 'Y'";

//on crée la requete
$select = "SELECT * FROM mm_modele WHERE region='$region' AND cat='modele' AND cache='non'";

if (!empty($choix))
$select .= " AND (".join(" ".$operateur." ", $choix).")";

$select.= "ORDER BY login ASC ";

Voila :)

Merci à vous.

PS: Oui, oui, je me suis fait aider sur ce coup la :D

Lien vers le commentaire
Partager sur d’autres sites

Ah oui, c'est vrai, pourquoi faire simple quand on peut faire compliqué ! :P

$operateur=$_POST['operateur'];
$region=$_POST['region'];

$tab=array('mode', 'publicité', 'glamour', etc..);

for($i; $i<count($tab); $i++)
if (isset($_POST['choix$i'])) $choix[] = $tab[$i]." = 'Y'";


//on crée la requete
$select = "SELECT * FROM mm_modele WHERE region='$region' AND cat='modele' AND cache='non'";

if (!empty($choix))
$select .= " AND (".join(" ".$operateur." ", $choix).")";

$select.= "ORDER BY login ASC ";

Ca te va vraiment pas de faire ça ? :P

Lien vers le commentaire
Partager sur d’autres sites

  • 1 month later...

bonjour, quand au véritable sujet de ton poste soit l'optimisation des requetes mysql je te renvoie sur l'un des cours de mon charmant enseignant de SGBD (M.Perrin kikoo à lui :D)

Cours opti 3

bonne lecture avec tout ce post ca devrait pas ramer meme si la planete entiere s'y connecte :P

Modifié par barrak
Lien vers le commentaire
Partager sur d’autres sites

Veuillez vous connecter pour commenter

Vous pourrez laisser un commentaire après vous êtes connecté.



Connectez-vous maintenant
×
×
  • Créer...