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 :

$sql = '
SELECT *
FROM la table
WHERE
type = "'.$_POST['type'].'"
AND
publication="oui"
AND
prix BETWEEN "'.$_POST['budget_min'].'" AND "'.$_POST['budget_max'].'"
AND
nb_chambres BETWEEN "'.$_POST['chambre_min'].'" AND "'.$_POST['chambre_max'].'"
AND
surf_hab BETWEEN "'.$_POST['surf_min'].'" AND "'.$_POST['surf_max'].'"
AND
ville_offre LIKE "'.$_POST['ville1'].'%"
AND
ville_offre LIKE "'.$_POST['ville2'].'%"
AND
ville_offre LIKE "'.$_POST['ville3'].'%"
';


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:
$sql = '
SELECT *
FROM la table
WHERE
type = "'.$_POST['type'].'"
AND
publication="oui"
AND
prix BETWEEN "'.$_POST['budget_min'].'" AND "'.$_POST['budget_max'].'"
AND
nb_chambres BETWEEN "'.$_POST['chambre_min'].'" AND "'.$_POST['chambre_max'].'"
AND
surf_hab BETWEEN "'.$_POST['surf_min'].'" AND "'.$_POST['surf_max'].'"
AND
ville_offre LIKE "'.$_POST['ville1'].'%"
OR
ville_offre LIKE "'.$_POST['ville2'].'%"
OR
ville_offre LIKE "'.$_POST['ville3'].'%"
';
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 :
if (isset($_POST['envoyer']) && $_POST['envoyer'] == 'Envoyer') { 


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

if ($_POST['chambre_min']==NULL) {
$_POST['chambre_min']=="0"; }
if ($_POST['chambre_max']==NULL) {
$_POST['chambre_max']=="999999999999999"; }

if ($_POST['surf_min']==NULL) {
$_POST['surf_min']=="1"; }
if ($_POST['surf_max']==NULL) {
$_POST['surf_max']=="999999999999999"; }

if ($_POST['ville1']==NULL) {
$_POST['ville1']=="a"; }
if ($_POST['ville2']==NULL) {
$_POST['ville2']=="b"; }
if ($_POST['ville3']==NULL) {
$_POST['ville3']=="c"; }

$sql = '
SELECT *
FROM la table
WHERE
type = "'.$_POST['type'].'"
AND
publication="oui"
AND
prix BETWEEN "'.$_POST['budget_min'].'" AND "'.$_POST['budget_max'].'"
AND
nb_chambres BETWEEN "'.$_POST['chambre_min'].'" AND "'.$_POST['chambre_max'].'"
AND
surf_hab BETWEEN "'.$_POST['surf_min'].'" AND "'.$_POST['surf_max'].'"
AND
ville_offre LIKE "'.$_POST['ville1'].'%"
OR
ville_offre LIKE "'.$_POST['ville2'].'%"
OR
ville_offre LIKE "'.$_POST['ville3'].'%"
';


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)

<?php

define(SQL_SELECT_OFFERS, <<<EOS
select * from offers
where is_published
and type='%s'
and ville_offre in(%s)
and prix between %d and %d
and surface between %d and %d
EOS;
) ;

/** @param $soumis array paramètres de recherche
* @return array retourne un tableau des tuples résultant de la recherche
*/
function chercher($soumis)
{
if(array_key_exists('budget_min', $soumis)
$budget_min = is_null($soumis['budget_min'])
? 0
: $soumis['budget_min'] ;
else
die('Pas de budget min soumis') ;

if(array_key_exists('budget_max', $soumis)
$budget_min = is_null($soumis['budget_max'])
? 9999
: $soumis['budget_max'] ;
else
die('Pas de budget max soumis') ;

$villes = array() ;
if(array_key_exists('ville_1', $soumis)
$ville_1[] = is_null($soumis['ville_1'])
? 'sin city'
: $soumis['ville_1'] ;
else
die('Pas de budget max soumis') ;

// ... vérification des autres champs

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

// exec du SQL

return $resultats ;
}

$resultats = chercher($_POST) ;


?><!-- 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