Requete WHERE avec plusieurs BETWEEN ?

Répondre
vitchi
le 11/04/2008 à 15:04
vitchi
Salut tout le monde,

Une petite question concernant un probleme de requete pour un formulaire de recherche
Soit la requete suivante :

  1. $sql = '
  2. SELECT *
  3. FROM la table
  4. WHERE
  5. type = "'.$_POST['type'].'"
  6. AND
  7. publication="oui"
  8. AND
  9. prix BETWEEN "'.$_POST['budget_min'].'" AND "'.$_POST['budget_max'].'"
  10. AND
  11. nb_chambres BETWEEN "'.$_POST['chambre_min'].'" AND "'.$_POST['chambre_max'].'"
  12. AND
  13. surf_hab BETWEEN "'.$_POST['surf_min'].'" AND "'.$_POST['surf_max'].'"
  14. AND
  15. ville_offre LIKE "'.$_POST['ville1'].'%"
  16. AND
  17. ville_offre LIKE "'.$_POST['ville2'].'%"
  18. AND
  19. ville_offre LIKE "'.$_POST['ville3'].'%"
  20. ';


Savez vous pourquoi elle ne me retourne aucun resultat (renvoie zero enregistrement) si on ne saisie pas tous les champs du formulaire ?

Note: evidemment les champs existent dans la base, les $_POST correspondent bien aux champs du formulaire et la requete est bien executee sans erreur particuliere...:'(

Merci d'avance :)
vitchi
le 11/04/2008 à 15:07
vitchi
D'ailleurs ce serait plutot ça le requete:
  1. $sql = '
  2. SELECT *
  3. FROM la table
  4. WHERE
  5. type = "'.$_POST['type'].'"
  6. AND
  7. publication="oui"
  8. AND
  9. prix BETWEEN "'.$_POST['budget_min'].'" AND "'.$_POST['budget_max'].'"
  10. AND
  11. nb_chambres BETWEEN "'.$_POST['chambre_min'].'" AND "'.$_POST['chambre_max'].'"
  12. AND
  13. surf_hab BETWEEN "'.$_POST['surf_min'].'" AND "'.$_POST['surf_max'].'"
  14. AND
  15. ville_offre LIKE "'.$_POST['ville1'].'%"
  16. OR
  17. ville_offre LIKE "'.$_POST['ville2'].'%"
  18. OR
  19. ville_offre LIKE "'.$_POST['ville3'].'%"
  20. ';
LA GLOBULE
le 11/04/2008 à 15:28
LA GLOBULE
Tu dois utiliser des OR et non des AND.
En faisant des AND, tu imposes une condition d'obligation de résultats.
vitchi
le 11/04/2008 à 15:34
vitchi
slt globule,

Oui j'ai essaye de mettre des OR mais dans ce cas de figure, cela me retourne 100 resultats (soit tous les enregistrements de ma table :'( )
LA GLOBULE
le 11/04/2008 à 15:36
LA GLOBULE
Ben normal, vu que tu as des LIKE '%%', tous les enregistrements matchent.

Pour faire un truc plus précis, tu dois ajouter des conditions à ta recherche que si ta variable n'est pas vide.

Je m'explique : si $_POST['ville1'] est vide, tu dois générer une requete SQL sans la condition AND ville_offre LIKE "'.$_POST['ville1'].'%".
En fait, il faut "construire" ton $sql en fonction du contenu du POST.
vitchi
le 11/04/2008 à 15:41
vitchi
Ok je comprend mieux! Je pensais qu'en filtrant des le depart la requete avec le:

type = "'.$_POST['type'].'"

on limitait alors l'affichage des resultats au "type" etc.etc...
et non à tous les enregistrements
vitchi
le 11/04/2008 à 17:05
vitchi
Ok les gars je reviens à la charge :)

Le fait de construire la requete "petit" à "petit" comme le dit la globule fonctionne... mais si on imagine toutes les situations, ca fait bcp de code je trouve (si l'utilisateur saisit ce champ et pas celui ci etc etc... bcp de scenario possibles !)

Donc je me suis dis (en tant que flemmard :p), on a qu'a attribuer une valeur au champ si celui est "null" non?

Voici donc la requete :
  1. if (isset($_POST['envoyer']) && $_POST['envoyer'] == 'Envoyer') {


  2. //si l'utilisateur ne remplit pas les variables du formulaire, on va leur attribuer des valeurs pas defaut pour la recherche
  3. if ($_POST['budget_min']==NULL) {
  4. $_POST['budget_min']=="0"; }
  5. if ($_POST['budget_max']==NULL) {
  6. $_POST['budget_max']=="999999999999999"; }

  7. if ($_POST['chambre_min']==NULL) {
  8. $_POST['chambre_min']=="0"; }
  9. if ($_POST['chambre_max']==NULL) {
  10. $_POST['chambre_max']=="999999999999999"; }

  11. if ($_POST['surf_min']==NULL) {
  12. $_POST['surf_min']=="1"; }
  13. if ($_POST['surf_max']==NULL) {
  14. $_POST['surf_max']=="999999999999999"; }

  15. if ($_POST['ville1']==NULL) {
  16. $_POST['ville1']=="a"; }
  17. if ($_POST['ville2']==NULL) {
  18. $_POST['ville2']=="b"; }
  19. if ($_POST['ville3']==NULL) {
  20. $_POST['ville3']=="c"; }

  21. $sql = '
  22. SELECT *
  23. FROM la table
  24. WHERE
  25. type = "'.$_POST['type'].'"
  26. AND
  27. publication="oui"
  28. AND
  29. prix BETWEEN "'.$_POST['budget_min'].'" AND "'.$_POST['budget_max'].'"
  30. AND
  31. nb_chambres BETWEEN "'.$_POST['chambre_min'].'" AND "'.$_POST['chambre_max'].'"
  32. AND
  33. surf_hab BETWEEN "'.$_POST['surf_min'].'" AND "'.$_POST['surf_max'].'"
  34. AND
  35. ville_offre LIKE "'.$_POST['ville1'].'%"
  36. OR
  37. ville_offre LIKE "'.$_POST['ville2'].'%"
  38. OR
  39. ville_offre LIKE "'.$_POST['ville3'].'%"
  40. ';


Or là encore une fois cela me retourne tous les resultats de ma table...

Si qq1 a une solution :)))))
LupusMic
le 11/04/2008 à 17:44
LupusMic
Plusieurs remarques d'ordre générales :
- like est à bannir
- il faut tester la requête manuellement avant de l'intégrer au PHP
- il ne faut pas construire la requête à l'exécution
- isset est un faux ami, il faut lui préférer array_key_exists
- faut savoir si tu as besoin de nettoyer les données soumises avant de les injecter dans ta base.
- l'usage du sélecteur universel * peut dégrader les performances de la requête.
- si on utilises une constante numérique, il y a de forte chance qu'elle changera dans le temps (le nivellement des prix par exemple).
- die() n'est pas à utiliser en production
- du code qui est copié-collé à de forte chances de pouvoir être factorisé (en écrivant une fonction générique par exemple)

  1. <?php

  2. define(SQL_SELECT_OFFERS, <<<EOS
  3. select * from offers
  4. where is_published
  5. and type='%s'
  6. and ville_offre in(%s)
  7. and prix between %d and %d
  8. and surface between %d and %d
  9. EOS;
  10. ) ;

  11. /** @param $soumis array paramètres de recherche
  12. * @return array retourne un tableau des tuples résultant de la recherche
  13. */
  14. function chercher($soumis)
  15. {
  16. if(array_key_exists('budget_min', $soumis)
  17. $budget_min = is_null($soumis['budget_min'])
  18. ? 0
  19. : $soumis['budget_min'] ;
  20. else
  21. die('Pas de budget min soumis') ;

  22. if(array_key_exists('budget_max', $soumis)
  23. $budget_min = is_null($soumis['budget_max'])
  24. ? 9999
  25. : $soumis['budget_max'] ;
  26. else
  27. die('Pas de budget max soumis') ;

  28. $villes = array() ;
  29. if(array_key_exists('ville_1', $soumis)
  30. $ville_1[] = is_null($soumis['ville_1'])
  31. ? 'sin city'
  32. : $soumis['ville_1'] ;
  33. else
  34. die('Pas de budget max soumis') ;

  35. // ... vérification des autres champs

  36. $sql = sprintf(SQL_SELECT_OFFERS, $type, implode(',', $villes), $budget_min, $budget_max, $surface_min, $surface_max) ;

  37. // exec du SQL

  38. return $resultats ;
  39. }

  40. $resultats = chercher($_POST) ;


  41. ?><!-- Su ce site, la coloration syntaxique des bouts de code PHP n'est prise en compte que si tu entoure ton code comem dans un script PHP -->


C'est un exemple très perfectible, pour essayer de te donner quelques éléments pour avancer. Et il n'y a jamais une seule solution en programmation.

Ne copie-colle pas bêtement, on apprend rien sans réflexion ©.
Développeur récurrent, procédural et relationnel. Caustique soupe-au-lait.
vitchi
le 11/04/2008 à 17:53
vitchi
Coucou,

Je vais tester ça, je te tiens au courant car cela a l'air tres interessant, ce n'est en effet pas du tout ce genre d'approche à laquelle je pensais!!!.

note: Sinon je ne suis en general pas adepte du copier/coller ;)

Par contre:
" l'usage du sélecteur universel * peut dégrader les performances de la requête."
Sur ce point, je pense qu'il y a plusieurs ecoles car depuis le temps que je lis des points de vue divergents à gauche, à droite (pour certain
la perte de performance est marginale, pour d'autres elle est consequente... si tu pouvais developper ton point de vue cela m interesserait!)
vitchi
le 11/04/2008 à 17:57
vitchi
Erf je peux pas editer mon post precedent, je reposte desole
----

Cependant, bien que je vais regarder ton code, qq1 pourrait m'expliquer en quoi ma requete precedente ne fonctionne pas? (car je ne comprends pas et...ben j'aimerai comprendre mon erreur :p)
Répondre
LoadingChargement en cours