8791 sujets

Développement web côté serveur, CMS

Bonjour à tous,

je suis débutant en Mysql. J essaye (à titre d'exercice) de faire un site d'agence immobilière. J'ai donc créé une base de données comportant les tables suivantes : biens, type_biens(=Maison, appartement, studio…), statut_bien (=a vendre, vendu, a louer, loué…), link_statut(permettant de faire la liaison entre biens et statut_bien) et communes.

Je souhaites afficher toutes les maisons à vendre et afficher la commune correspondante. J'arrive sans problème à afficher les maisons à vendre mais lorsque je lui demande d'afficher également la commune correspondant au bien, pour tous les biens, il m'affiche toutes les communes. Pour faire plus simple, si j'ai 4 biens de 4 communes différentes, au lieu de m'afficher les 4 biens avec leur commune respective, il m'affiche 4 X 4 soit 16 biens.

J'ai essayé avec des sous-requêtes, avec une table temporaire (càd mettre le résultat dans une table et pour chaque élément de cette table afficher la commune) mais ça ne marche pas.

Quelqu'un aurait une idée?

Voici ci-dessous la construction de ma base de données.

Merci de m'avoir lu et d'avance merci à tous ceux qui m'apporteront leur aide.

DROP TABLE IF EXISTS `biens`;

CREATE TABLE `biens` (
  `id_biens` int(11) NOT NULL AUTO_INCREMENT,
  `adresse` varchar(250) NOT NULL,
  `pays` varchar(70) NOT NULL DEFAULT 'Belgique',
  `prix` mediumint(25) NOT NULL,
  `description` text NOT NULL,
  `code_bien` char(11) NOT NULL,
  PRIMARY KEY (`id_biens`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;

LOCK TABLES `biens` WRITE;
/*!40000 ALTER TABLE `biens` DISABLE KEYS */;
INSERT INTO `biens` (`id_biens`,`adresse`,`pays`,`prix`,`description`,`code_bien`)
VALUES
	(1,'Avenue du Parc','Belgique',213000,'Jolie Petite maison d\'habitation','10'),
	(2,'Rue des Sciences','Belgique',275000,'Splendide Villa 4 facades','20'),
	(3,'Avenue de la piscine','Belgique',543000,'Immeuble de rapport avec nombreux garages','10'),
	(4,'Chausse d\'Hacht','Belgique',123000,'Appartement 2 chambres','30'),
	(5,'Rue de la fontaine','Belgique',321000,'Maison à restaurer','30');

/*!40000 ALTER TABLE `biens` ENABLE KEYS */;
UNLOCK TABLES;


# Dump of table communes
# ------------------------------------------------------------

DROP TABLE IF EXISTS `communes`;

CREATE TABLE `communes` (
  `id_commune` int(11) NOT NULL AUTO_INCREMENT,
  `code_postal` mediumint(5) NOT NULL,
  `ville` varchar(75) NOT NULL,
  `commune` varchar(75) NOT NULL,
  `langue` varchar(2) NOT NULL,
  PRIMARY KEY (`id_commune`),
  KEY `code_postal` (`code_postal`),
  KEY `ville` (`ville`),
  KEY `commune` (`commune`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8;

LOCK TABLES `communes` WRITE;
/*!40000 ALTER TABLE `communes` DISABLE KEYS */;
INSERT INTO `communes` (`id_commune`,`code_postal`,`ville`,`commune`,`langue`)
VALUES
	(1,1000,'Bruxelles','Bruxelles','FN'),
	(2,1000,'Bruxelles','Laeken (Bru.)','FN'),
	(3,1000,'Bruxelles','Neder-over-Heembeek (Bru.)','FN'),
	(4,1000,'Bruxelles','Haren (Bru.)','FN'),
	(5,1030,'Bruxelles','Schaerbeek','FN'),
	(6,1040,'Bruxelles','Etterbeek','FN'),
	(7,1050,'Bruxelles','Ixelles','FN'),
	(8,1060,'Bruxelles','Saint-Gilles','FN'),
	(9,1070,'Bruxelles','Anderlecht','FN'),
	(10,1080,'Bruxelles','Molenbeek-Saint-Jean','FN'),
	(11,1081,'Bruxelles','Koekelberg','FN'),
	(12,1082,'Bruxelles','Berchem-Sainte-Agathe','FN'),
	(13,1083,'Bruxelles','Ganshoren','FN'),
	(14,1090,'Bruxelles\n','Jette','FN'),
	(15,1140,'Bruxelles','Evere','FN'),
	(16,1150,'Bruxelles','Woluwe-Saint-Pierre','FN'),
	(17,1160,'Bruxelles','Auderghem','FN'),
	(18,1170,'Bruxelles','Watermael-Boitsfort','FN'),
	(19,1180,'Bruxelles','Uccle','FN'),
	(20,1190,'Bruxelles','Forest','FN'),
	(21,1200,'Bruxelles','Woluwe-Saint-Lambert','FN'),
	(22,1210,'Bruxelles','Saint-Josse-ten-Noode','FN');

/*!40000 ALTER TABLE `communes` ENABLE KEYS */;
UNLOCK TABLES;


# Dump of table link_communes
# ------------------------------------------------------------

DROP TABLE IF EXISTS `link_communes`;

CREATE TABLE `link_communes` (
  `id_biens` int(11) NOT NULL,
  `code_postal` mediumint(5) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

LOCK TABLES `link_communes` WRITE;
/*!40000 ALTER TABLE `link_communes` DISABLE KEYS */;
INSERT INTO `link_communes` (`id_biens`,`code_postal`)
VALUES
	(1,5),
	(2,6),
	(3,1),
	(4,5),
	(5,1);

/*!40000 ALTER TABLE `link_communes` ENABLE KEYS */;
UNLOCK TABLES;


# Dump of table link_statut
# ------------------------------------------------------------

DROP TABLE IF EXISTS `link_statut`;

CREATE TABLE `link_statut` (
  `id_biens` mediumint(11) NOT NULL,
  `code_statut` char(5) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

LOCK TABLES `link_statut` WRITE;
/*!40000 ALTER TABLE `link_statut` DISABLE KEYS */;
INSERT INTO `link_statut` (`id_biens`,`code_statut`)
VALUES
	(1,'10'),
	(2,'20'),
	(3,'10'),
	(4,'30'),
	(5,'10');

/*!40000 ALTER TABLE `link_statut` ENABLE KEYS */;
UNLOCK TABLES;


# Dump of table statut_bien
# ------------------------------------------------------------

DROP TABLE IF EXISTS `statut_bien`;

CREATE TABLE `statut_bien` (
  `id_statut` int(11) NOT NULL AUTO_INCREMENT,
  `code_statut` char(5) NOT NULL,
  `statut_bien` varchar(50) NOT NULL,
  PRIMARY KEY (`id_statut`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

LOCK TABLES `statut_bien` WRITE;
/*!40000 ALTER TABLE `statut_bien` DISABLE KEYS */;
INSERT INTO `statut_bien` (`id_statut`,`code_statut`,`statut_bien`)
VALUES
	(1,'10','a vendre'),
	(2,'15','vendu'),
	(3,'20','a louer'),
	(4,'25','loue');

/*!40000 ALTER TABLE `statut_bien` ENABLE KEYS */;
UNLOCK TABLES;


# Dump of table type_biens
# ------------------------------------------------------------

DROP TABLE IF EXISTS `type_biens`;

CREATE TABLE `type_biens` (
  `id_type_biens` int(11) NOT NULL AUTO_INCREMENT,
  `code_bien` char(11) NOT NULL,
  `type_bien` varchar(50) NOT NULL,
  PRIMARY KEY (`id_type_biens`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=latin1;

LOCK TABLES `type_biens` WRITE;
/*!40000 ALTER TABLE `type_biens` DISABLE KEYS */;
INSERT INTO `type_biens` (`id_type_biens`,`code_bien`,`type_bien`)
VALUES
	(1,'10','Maison'),
	(2,'20','Appartement'),
	(3,'30','Studio'),
	(4,'40','Magasin'),
	(5,'50','Bureau');

/*!40000 ALTER TABLE `type_biens` ENABLE KEYS */;
UNLOCK TABLES;

Modifié par paintbox (05 Apr 2010 - 01:30)
Salut,

il y a plusieurs erreurs dans la structure des tables :
* un bien a 1 et 1 seul statut donc la table link_statut est inutile et il faudrait rajouter un champ id_statut dans la table biens
* un bien ne se trouve que dans 1 et 1 seule commune donc la table link_communes est inutile et il faudrait rajouter un champ id_commune dans la table biens
* je n'ai pas compris à quoi correspondait le champ code_bien ?
* je n'ai pas compris à quoi correspondait le champ code_statut ?

Après cela tu y verras plus clair je pense. Smiley cligne
Modifié par Heyoan (21 Mar 2010 - 23:40)
Bonjour Heyoan,

merci pour ta réponse.

* J'ai fais une table link_statut parce que je me suis dis qu'un bien pouvait passer(dans le temps) du statut "à vendre" à "à loué" ou "vendu". Mais c'est vrai qu'il ne peut avoir qu'un seul statut à la fois

* ok pour commune, effectivement un bien ne se trouve que dans une seule commune

* le champ code_bien sert à lier la table biens avec la table type_biens

J'avoue que je m'embrouille encore un peu lorsque je dois construire mes tables.
paintbox a écrit :
* J'ai fais une table link_statut parce que je me suis dis qu'un bien pouvait passer(dans le temps) du statut "à vendre" à "à loué" ou "vendu". Mais c'est vrai qu'il ne peut avoir qu'un seul statut à la fois
Yep... et si tu veux historiser les modifications de statut d'un bien tu peux effectivement créer une table historique_statut
* id_historique (clef primaire auto_increment)
* id_bien
* id_statut
* date_modification

paintbox a écrit :
* le champ code_bien sert à lier la table biens avec la table type_biens
Il est donc inutile (tout comme code_statut) puisque id_type_biens suffit déjà à faire un lien unique.

paintbox a écrit :
J'avoue que je m'embrouille encore un peu lorsque je dois construire mes tables.
Alors il faut faire une recherche sur "cardinalités Merise" par exemple et les règles sont assez simples... même s'il faut pratiquer un petit peu.


Edit: pour te donner une idée il y a une règle qui dit que pour une relation entre deux tables ayant les cardinalités (1,1) <=> (0,n) la clef primaire de la seconde table devient une clef étrangère de la première.
Redit en clair :
* un bien est localisé dans 1 et 1 seule commune => cardinalité (1,1)
* une commune peut abriter 0 ou plusieurs biens => cardinalité (0,n)
donc il faut rajouter un champ id_commune à la table biens.
Fastoche non ! Smiley lol

Par contre si tu avais une table caractéristiques (garage, jardin, vue sur la mer, puits, etc.) on aurait :
* un bien possède 0 ou plusieurs de ces caractéristiques => cardinalité (0,n)
* une caractéristique est possédée par 0 ou plusieurs biens => cardinalité (0,n)
Et dans ce cas il faudrait créer une nouvelle table caractéristiques_bien reprenant les clefs primaires de ces 2 tables :
* id_caracteristique_bien (clef primaire auto_increment)
* id_bien
* id_caracteristique


Edit2: et comme bien souvent il y a un tuto qui va bien sur developpez.com.
Modifié par Heyoan (22 Mar 2010 - 00:18)
En fait, les champs code_statut et code_bien me servent à créer des catégories.
exemple pour la table type_bien, le champ code_bien peut être égale à : 10=Maison, 20=Appartement, 30=Studio…

En utilisant un intervalle de 10, je peux encore insérer 9 sous catégories à la catégorie 10. J'avais lu cela dans un bouquin plutôt que d'utiliser la clé primaire.
paintbox a écrit :
En utilisant un intervalle de 10, je peux encore insérer 9 sous catégories à la catégorie 10. J'avais lu cela dans un bouquin plutôt que d'utiliser la clé primaire.
Ben autant ça peut avoir du sens dans certains cas comme par exemple pour un statut de commande (00 = commande passée / 10 = en cours de préparation / 20 = BL édité / 30 = livrée / etc.) autant ici avec des libellés alphanumériques je ne vois aucun intérêt.
Modifié par Heyoan (22 Mar 2010 - 09:19)
Hello Heyoan,

j'ai suivi tes conseils, et cela marche beaucoup mieux.
Je continue mon projet jusqu'au prochain obstacle.

Merci encore pour tes conseils
Bonjour Heyoan,

j'ai suivis tes conseils, mes jointures fonctionnent parfaitement.
J'ai juste encore un problème.

j'ai fait une fonction qui récupère du menu($choix_type, $choix_statut) le choix (type de bien et type de statut ex: appartement à vendre) fait par l'utilisateur.

La récupération se fait visiblement très bien puisque dans ma fonction je demande d'afficher les choix faits par l'utilisateur. Ces choix sont mis dans ma requete MYSQL. Par contre je n'arrive pas à afficher le résultat.

Voici ma fonction :

function vendre ($choix_type, $choix_statut)
	{
	$choix_type=$choix_type;
	$choix_statut=$choix_statut;
	$request=mysql_query('SELECT biens.id_biens, biens.prix, biens.description, type_biens.type_bien, statut_bien.statut_bien, communes.commune, communes.code_postal FROM biens 
	INNER JOIN communes ON biens.id_commune=communes.id_commune 
	INNER JOIN type_biens ON biens.code_bien=type_biens.code_bien 
	INNER JOIN statut_bien ON biens.code_statut=statut_bien.code_statut 
	WHERE type_biens.code_bien="$choix_type" AND statut_bien.statut_bien="$choix_statut"');
	echo $choix_type." ";
	echo $choix_statut;
	While ($donnees=mysql_fetch_array($request) or die (mysql_error()))//Boucle
	{
	echo '<table>';
		echo '<tr>';
		echo '<td>'.$donnees["type_bien"]."<br /> "."<br />" .$donnees["commune"]."<br />".$donnees["prix"].'</td>';
	echo '</tr>';
	}
	echo '</table>';
	}


As-tu une idée?

Merci d'avance
Salut,

ben il faudrait revoir les bases de PHP (par exemple sur http://phpdebutant.org/ ) :

* les lignes suivantes sont inutiles :
	$choix_type=$choix_type;
	$choix_statut=$choix_statut;

* il faut revoir la concaténation :
$variable = 'abc';
echo '<p>blabla $variable blabla</p>';
echo '<p>blabla '.$variable.' blabla</p>';
echo "<p>blabla $variable blabla</p>";
echo "<p>blabla ".$variable." blabla</p>";

* le or die est à associer à mysql_query et pas à mysql_fetch_array.

* etc.
Hello Heyoan,

merci pour ta réponse.

Oui en effet ces 2 lignes ne sont pas nécessaires, je les avais mis pour vérifier mes variables.
$choix_type=$choix_type; 
    $choix_statut=$choix_statut;



Je ne vois pas très bien où ma concaténation n'est pas correcte. J'ai beau chercher, je ne trouve pas.

Peux-tu me donner une piste?

Merci