Requete avec subquery

Mammouth du PHP | 965 Messages

05 nov. 2007, 11:21

Bonjour,

comme la requetes est en sql mais qu'elle est appelé depuis php je la met dans cette rubrique, donc la fonction fait une requete sur plusieurs tables avec un SELCT IN :
$Req_sql = mysql_query("SELECT * FROM lot,programme WHERE Id_region IN ( SELECT Id_region,Id_fiscalite FROM programme WHERE Id_Region LIKE '".$Option2."' AND Id_fiscalite  LIKE '".$Option1."') AND Id_genre LIKE '".$Option3."' AND Prix_base BETWEEN '".$Prix_min."' AND '".$Prix_max."' ") or die(mysql_error());
$Array_sql = mysql_fetch_array($Req_sql);
Cette requete retourne l'erreur suivante :
Operand should contain 1 column(s)
Pourtant l'operant contient une colonne, même mieux, deux.

J'arrive pas a voir d'ou viens l'erreur une idée ?

d0m
Mammouth du PHP | 1141 Messages

05 nov. 2007, 11:31

Pourtant l'operant contient une colonne, même mieux, deux.
j'aurais plutôt dis :
"Pourtant l'operant contient une colonne, même pire, deux. "

Avec l'opérateur IN, tu va comme = comparer Id_region à une valeur.
Hors là tu lui en donnes 2, les 2 résultats de ton SELECT.
c'est comme si tu écrivais:

Code : Tout sélectionner

SELECT * FROM lot,programme WHERE Id_region = Id_region,Id_fiscalite
Ca ne veut rien dire.

Ton SELECT de la sous requête doit retourner 1 seul champ, celui qui équivaut à Id_region.

Mammouth du PHP | 965 Messages

05 nov. 2007, 11:35

yep résolu finalement
$Req_sql = mysql_query("SELECT * FROM lot,programme WHERE (Id_region,Id_fiscalite) IN ( SELECT Id_region,Id_fiscalite FROM programme WHERE Id_Region LIKE '".$Option2."' AND Id_fiscalite  LIKE '".$Option1."') AND Id_genre LIKE '".$Option3."' AND Prix_base BETWEEN '".$Prix_min."' AND '".$Prix_max."' ") or die(mysql_error());
$Array_sql = mysql_fetch_array($Req_sql);

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

05 nov. 2007, 11:38

Rien de plus à ajouter aux explications de d0m, juste une petite remarque sur le fait qu'une jointure entre tes tables serait bien plus appropriée qu'une sous requête

Code : Tout sélectionner

SELECT ... FROM table1, table2 WHERE table1.champX = table2.champY AND table1.champZ = ... ...
Par ailleurs, si tu fais une comparaison identique de valeur, utilises l'opérateur "=" au lieu de "LIKE", ne mets pas d'apostrophes autour de valeurs numériques, et liste les champs que tu souhaites récupérer au lieu de faire un SELECT * (cf. la FAQ pour en savoir un peu plus sur les bonnes pratiques SQL ;))
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Mammouth du PHP | 965 Messages

05 nov. 2007, 12:01

Rien de plus à ajouter aux explications de d0m, juste une petite remarque sur le fait qu'une jointure entre tes tables serait bien plus appropriée qu'une sous requête

Code : Tout sélectionner

SELECT ... FROM table1, table2 WHERE table1.champX = table2.champY AND table1.champZ = ... ...
Par ailleurs, si tu fais une comparaison identique de valeur, utilises l'opérateur "=" au lieu de "LIKE", ne mets pas d'apostrophes autour de valeurs numériques, et liste les champs que tu souhaites récupérer au lieu de faire un SELECT * (cf. la FAQ pour en savoir un peu plus sur les bonnes pratiques SQL ;))
Il n'y a pas de jonctions entre les tables, j'utilise le LIKE puisque ma requete contient comme valeur par defaut le joker sql %, ce qui permet de faire une recherche avec LIKE '%'.

Modérateur PHPfrance
Modérateur PHPfrance | 7636 Messages

05 nov. 2007, 12:09

comme la requetes est en sql mais qu'elle est appelé depuis php je la met dans cette rubrique
Oui et comme ma voiture consome de l'essence je me dis que c'est bien de l'amener chez le pompiste pour apprendre à la conduire.

:arrow: Je déplace

/!\ Avant de poster se documenter et rechercher.
Qui ne sait pas rendre un service n'a pas le droit d'en demander.
MaBrute

Mammouth du PHP | 965 Messages

05 nov. 2007, 12:22

comme la requetes est en sql mais qu'elle est appelé depuis php je la met dans cette rubrique
Oui et comme ma voiture consome de l'essence je me dis que c'est bien de l'amener chez le pompiste pour apprendre à la conduire.

:arrow: Je déplace
:oops:

sinon en fait c'était beaucoup plus simple de faire comme ca :
$Req_sql = mysql_query("SELECT * FROM lot,programme WHERE Id_region LIKE '".$Option2."' AND Id_fiscalite LIKE '".$Option1."' AND Id_genre LIKE '".$Option3."' AND Prix_base BETWEEN '".$Prix_min."' AND '".$Prix_max."' ") or die(mysql_error());
:roll:

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

05 nov. 2007, 12:25

Il n'y a pas de jonctions entre les tables
Doit quand même bien y avoir un lien entre la table "programme" de ta requête principale et la table "programme" de ta sous requête nan ? Pourquoi faire simple... ;)
Au lieu de :

Code : Tout sélectionner

WHERE (Id_region,Id_fiscalite) IN ( SELECT Id_region,Id_fiscalite FROM programme WHERE Id_Region LIKE '".$Option2."' AND Id_fiscalite LIKE '".$Option1."' )
Pourquoi ne pas simlpement faire

Code : Tout sélectionner

WHERE Id_Region LIKE '".$Option2."' AND Id_fiscalite LIKE '".$Option1."'
:?:
j'utilise le LIKE puisque ma requete contient comme valeur par defaut le joker sql %, ce qui permet de faire une recherche avec LIKE '%'.
C'est pas mieux pour autant. Au lieu d'ajouter une condition qui filtre ta requête en autorisant tout, ce qui aura pour effet de scanner toute ta table pour s'assurer que tous tes enregistrements correspondent bien à la valeur recherchée, suffit juste de ne pas mettre la condition :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Mammouth du PHP | 965 Messages

05 nov. 2007, 12:31

Merci Ryle mais quand je fais plusieurs recherche sur une table je veux laisser des conditions vides, comme par exemple SELCT * FROM machin WHERE truc = % AND bidule = 1000 .

En fait c'est pour un moteur de recherche, donc toute les conditions ne sont pas forcement envoyées.

Mammouth du PHP | 965 Messages

05 nov. 2007, 12:43

Quand je fais ce type de requete :
$Req_Liste_Lot = mysql_query("SELECT * FROM `lot`,`programme` WHERE Id_genre LIKE '".$Option3."' AND Prix_base BETWEEN '".$Prix_min."' AND '".$Prix_max."' AND Id_region LIKE '".$Option2."' AND Id_fiscalite LIKE '".$Option1."' ") or die(mysql_error());
	
	while($Array_Liste_Lot = mysql_fetch_array($Req_Liste_Lot))
	{ blablablabla }
Il me retourne 3 fois chaque entrée du tableau, quand je retire la requete sur programme et que je vire les 2 AND de la fin ca me retourne bien qu'un enregistrement a chaque fois.

Je ne comprends pas pourquoi il me retourne 3 fois chaque entrée, une idée ?

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

05 nov. 2007, 12:51

  • poste le schéma des tables pertinentes à ta requête sous la forme d'une instruction "CREATE TABLE"
  • poste tes requêtes telles qu'elles sont exécutées. Tout ce PHP nuit à la lecture. Ne mets pas toute ta requête sur une seule ligne si tu veux que les gens la lise et/ou comprenne
  • c'est normal que tu aies des résultats, tu joins 2 tables sans condition de jointure donc le serveur en fait le produit cartésien

Mammouth du PHP | 965 Messages

05 nov. 2007, 13:02

  • poste le schéma des tables pertinentes à ta requête sous la forme d'une instruction "CREATE TABLE"
  • poste tes requêtes telles qu'elles sont exécutées. Tout ce PHP nuit à la lecture. Ne mets pas toute ta requête sur une seule ligne si tu veux que les gens la lise et/ou comprenne
  • c'est normal que tu aies des résultats, tu joins 2 tables sans condition de jointure donc le serveur en fait le produit cartésien
Desole pour ne pas avoir tout mis d'un seul coup, finalement j'ai réussi a comprendre grace ton idée sur les jonctions de table, en effet si je ne foins rien c'est un peu n'importe quoi comme requete.

La reponse est :
SELECT * FROM `lot`
INNER JOIN programme ON (programme.Id = lot.Id_programme) 
WHERE Id_region LIKE '".$Option2."' AND Id_fiscalite LIKE '".$Option1."' AND Id_genre LIKE '".$Option3."' AND Prix_base BETWEEN '".$Prix_min."' AND '".$Prix_max."';

Mammouth du PHP | 965 Messages

05 nov. 2007, 13:24

Quand je fais cette requete en fait il ya toujours un probleme, cette fois ci, la requete se fait bien mais les reponses se font pour chaque ID commune.

les tables concernées :

Code : Tout sélectionner

CREATE TABLE `programme` ( `Id` int(11) NOT NULL auto_increment, `Nom` varchar(255) collate utf8_unicode_ci NOT NULL, `Adresse` varchar(255) collate utf8_unicode_ci default NULL, `Cp` varchar(5) collate utf8_unicode_ci NOT NULL, `Ville` varchar(70) collate utf8_unicode_ci NOT NULL, `Id_region` varchar(5) collate utf8_unicode_ci NOT NULL, `Date_comm` varchar(255) collate utf8_unicode_ci default NULL, `Date_livraison` varchar(255) collate utf8_unicode_ci default NULL, `Date_signature` varchar(255) collate utf8_unicode_ci default NULL, `Id_fiscalite` varchar(5) collate utf8_unicode_ci NOT NULL, `Presentation` text collate utf8_unicode_ci, `Photo_0` varchar(255) collate utf8_unicode_ci default NULL, `Photo_1` varchar(255) collate utf8_unicode_ci default NULL, `Photo_2` varchar(255) collate utf8_unicode_ci default NULL, UNIQUE KEY `Id` (`Id`), KEY `id_region` (`Id_region`), KEY `id_fiscalite` (`Id_fiscalite`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4 ;
et

Code : Tout sélectionner

CREATE TABLE `lot` ( `Id` int(11) NOT NULL auto_increment, `Id_programme` int(11) NOT NULL, `Code` varchar(10) collate utf8_unicode_ci NOT NULL, `Etage` int(2) default NULL, `Rentabilite` float default NULL, `Id_genre` varchar(5) collate utf8_unicode_ci NOT NULL, `Id_orientation` varchar(5) collate utf8_unicode_ci NOT NULL, `Id_type` varchar(5) collate utf8_unicode_ci NOT NULL, `Surface_total` float default NULL, `Surface_hab` float default NULL, `Prix_base` float default NULL, `Prix_pack2` float default NULL, `Loyer_mensuel` float default NULL, `Loyer_borloo` float default NULL, `Loyer_robien` float default NULL, `Infos_supp` text collate utf8_unicode_ci NOT NULL, `Id_etat` enum('signature','uncom','option','fax','reserv','disponible') collate utf8_unicode_ci NOT NULL default 'disponible', `Date_chgmt_etat` datetime default NULL, `Livraison` varchar(255) collate utf8_unicode_ci default NULL, `Id_vendeur` int(11) NOT NULL, `Nom_vendeur` varchar(255) collate utf8_unicode_ci default NULL, `Acheteur` varchar(255) collate utf8_unicode_ci default NULL, PRIMARY KEY (`Id`), KEY `id_programme` (`Id_programme`), KEY `id_genre` (`Id_genre`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=4 ;
La fonction :


function Lister_Lots($Option1,$Option2,$Option3,$Prix_min,$Prix_max)
{

$Req_Liste_Lot = mysql_query("
SELECT * FROM `lot` 
INNER JOIN programme ON (programme.Id = lot.Id_programme) 
WHERE Id_region LIKE '".$Option2."' 
AND Id_fiscalite LIKE '".$Option1."' 
AND Id_genre LIKE '".$Option3."' 
AND Prix_base BETWEEN '".$Prix_min."' 
AND '".$Prix_max."' ") or die(mysql_error());

	while($Array_Liste_Lot = mysql_fetch_array($Req_Liste_Lot))
	{
?>
			<tr>
			<td><?php echo $Array_Liste_Lot['Cp']; ?></td>
			<td><?php echo $Array_Liste_Lot['Ville']; ?></td>
			<td><?php echo $Array_Liste_Lot['Id']; ?></td>
			<td><?php echo $Array_Liste_Lot['Id_type']; ?></td>
			<td><?php echo $Array_Liste_Lot['Id_genre']; ?></td>
			<td><?php echo $Array_Liste_Lot['Etage']; ?></td>
			<td><?php echo $Array_Liste_Lot['Id_etat']; ?></td>  	
			<td><?php echo $Array_Liste_Lot['Prix_base']; ?></td> 
			<td><?php echo $Array_Liste_Lot['Loyer_mensuel']; ?></td>
			</tr>
			
<?php	
	}
}

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

05 nov. 2007, 13:44

C'est bien, on avance presque. Maintenant il ne te reste plus qu'à poster ta requête telle qu'elle est exécutée, plutôt que tout ce PHP qui ne nous sert à rien.

Mammouth du PHP | 965 Messages

05 nov. 2007, 13:48

C'est bien, on avance presque. Maintenant il ne te reste plus qu'à poster ta requête telle qu'elle est exécutée, plutôt que tout ce PHP qui ne nous sert à rien.
Elle depend des parametres envoyées par la recherche et donc n'est pas éxecutée de la même maniere a chaque fois.

SINON :
SELECT * FROM `lot`
INNER JOIN programme ON (programme.Id = lot.Id_programme)
WHERE Id_region LIKE 'O'
AND Id_fiscalite LIKE 'ROB'
AND Id_genre LIKE 'APPA'
AND Prix_base BETWEEN '0' AND '200'