une requête difficile avec double relation

Petit nouveau ! | 7 Messages

12 juin 2011, 02:02

bonjours je vous expose mon problème

je suis entrain de faire une application pour une commune en tant que stagiaire, il me manque une requête
Propriétaire adresse locataire
Ma base de données sous le conseils de mes profs est montée comme ca

une table batiment avec un id batiment et un #idpropriétaire

et une table Administres avec un idAdm #idBatiment

moi a partir de la je dois extraire les propriétaires du bâtiments que l'utilisateur choisis dans une liste qui me déroule tout les administres. et c'est dans le formulaire des administré que l'ont saisie le l'adresse de chaque locataires, pour extraire les locataires pas de problemes mais je n'arrive pas à extraire les propriétaires, en fait ces 2 tables ont une doubles relations du style M.Untel est propriétaire de tel batiment ou habite MTartenpion, je vous montre ma requête qui me donne le nom le prénom l'adresse de chaque personne mais je voudrai les propriétaires;

je sais cette requ^te est difficile mais y bien une tronche qui va m'aider :idea:

lien pour mes tables j'ai fait la double relation bien que mysql s'en moquehttp://www.flickr.com/photos/63935894@N02/
<?php

include("../commun/params.inc.php");
$data="";
$req="";
$db="";
$sql="";
$retour="";
$Non="";
$Prenom="";
$IdBat="";
$IdAdm="";
$IdBatiment="";
$NomProp="";
$Numero="";
$TypeVoie="";
$Voie="";
$total="";
$Idvoie="";
$totgen=0;
include("../php/menuinclude.php");
// je me connecte à MySQL
$db=mysql_connect(MYSQL_SERVER,MYSQL_LOGIN,MYSQL_PASSWORD) or die(mysql_error());


//je sélectionne la base
mysql_select_db(MYSQL_DATABASE,$db) or die(mysql_error());

//requete des voies

$requete="select b.IdVoie as IdVoie,v.Voie as Voie,t.TypeVoie as TypeVoie FROM TAdministres as a,TBatiments as b,TVoies as v,TTypesVoie as t
WHERE b.IdBatiment=a.IdBat AND v.Idvoie=b.Idvoie AND t.IdTypeVoie=v.IdTypeVoie
GROUP BY IdVoie ORDER BY v.Voie;";
$retour= mysql_query($requete) or die(mysql_error());
while ($ligne=mysql_fetch_assoc($retour)){
foreach($ligne as $champ=>$valeur)
$$champ=$valeur;
// la requete SQL
$sql = "SELECT a.Nom AS Nom, a.Prenom AS Prenom, v.IdVoie AS IdVoie, v.Voie AS Voie, t.TypeVoie AS TypeVoie, b.Numero AS Numero,Nom as NomProp
FROM TAdministres AS a,TBatiments as b,TTypesVoie as t, TVoies as v
WHERE a.IdBat=b.IdBatiment and b.IdVoie=v.IdVoie and v.IdTypeVoie=t.IdTypeVoie and b.IdVoie='$IdVoie' and b.IdProprietaire='$IdAdm'
ORDER BY IdVoie,Numero,Nom,Prenom,NomProp;";
//la requete des propriétair

// on envoie la requête
$req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error());
$total=mysql_num_rows($req);
// on fait une boucle qui va faire un tour pour chaque enregistrement
echo "<div id='page'>";
echo "<br><p>Voie : $TypeVoie $Voie</p><br><br>";
echo"<table>
<tr><th>Pro</th>
<th>Nom</th>
<th>Prenom</th>
<th>Num</th>

</tr>";
while($data = mysql_fetch_array($req))
{
// on récupère les variables correspondant aux champs et leurs valeurs
foreach($data as $champ=>$valeur)
$$champ=$valeur;
// on affiche les informations de l'enregistrement en cours

echo"
<tr><td>$NomProp</td>
<td>$Nom</td>
<td>$Prenom</td>
<td>$Numero</td>

</tr>";


}
echo "</table>";
$totgen+=$total;
echo "<br><br><br>Total : $total habitant";
echo ($total>1)?"s":"";
"</div>";
echo "<br><br>";

}// fin de boucle des voies

echo "<br><br>total pour toutes les voies : $totgen habitant";
echo ($totgen>1)?"s":"";

// on ferme la connexion à mysql


mysql_close();

?>
</div>
</body>
</html>

devlop78
Invité n'ayant pas de compte PHPfrance

12 juin 2011, 02:31

Je n'ai pas trop compris la question, c'est un peu flou. Quelles sont tes tables exactement ?

Pour les jointures, les requêtes avec jointures JOIN seront plus faciles à lire. Et quant à l'écriture, personnellement, l'indentation m'aide beaucoup

SELECT
table1.machin,
table1.truc,
table2.bidule
FROM
table1
INNER JOIN
table2 ON table2.id_table1 = table1.id

etc.

Petit nouveau ! | 7 Messages

12 juin 2011, 03:01

voici mes tables
http://www.flickr.com/photos/63935894@N02/

le problème c'est la double relation je m'explique
Un propriétaire est un administré, et le locataire aussi, donc il faut faire le trie des adm et des propriétaires sachant que dans la table bâtiments il y a un id Propriétaire qui doit être reliée à l'id bâtiment ou administre,

exemple : M.tata idadm774 est le propriétaire de M.toto idadm 120,
les locataires et les propriétaires ne sont pas différencié dans la table administré, mais dans la table bâtiment j'attribut un propriétaire parmi les administrés, regardez mes tables vous comprendrez mieux c'est difficile à expliquer:

en tout cas merci de tout mon coeur de votre réponse je sais que cette requête est difficile,
mes tables sont justes car visés par mes profs.
A
Ps sorry pour les fautes mais je suis très fatiguée 48h que je sèche, et je ne pense pas dormir avant la solution.

devlop78
Invité n'ayant pas de compte PHPfrance

12 juin 2011, 03:32

J'ai failli crier quand j'ai vu la référence croisée, mais ton explique aide. Donc, effectivement, il n'y pas de référence croisée (sauf dans ton schéma ^^), mais je vais t'aider en te posant une question :

Comment fais-tu si tu considères que un propriétaire peut avoir plusieurs batiments ? Bien sûr, tu vas me dire que plusieurs FK de batiment peuvent pointer sur le propriétaire. Ok.

Comment fais-tu si un locataire loue ... En fait. Je n'ai pas fini ma question que je suis déjà perdu. les deux tables forme une sorte de cercle, et au final, on ne sait pas bien qui fait qui avec quoi. Question qui va te faire changer de schéma : Si un propriétaire de 2 batiments est aussi locataire de 2 autres, comment ça va se dégoupillé. Ce sera impossible. En re-réfléchissant même un simple propriétaire de 2 batiments, c'est impossible. Mais tu vois, rien que le fait que ce soit si difficile pour moi d'imaginer avec le schéma le détruit.

Il y a donc d'après moi deux points importants qui vont jouer sur la conception :

- Il faut une relation n:m entre batiments et locataires ou 1:n si un batiment n'a pas plusieurs locataires possibles. Pareils pour les propriétaires.
- Il faut définir quel rôle représente la relation entre batiment et locataire/propriétaire, puisque ta table des administrés est trop large.

je te propose donc de rajouter une table intermédiaire, qui aura une clé primaire, une référence au batiment, une référence à l'administré, et un role : locataire ou propriétaire.

Par exemple

Administrés :
- id 5 Antoine
- id 7 Marc

Batiments :
- id 2 PARIS
- id 3 MARSEILLE
- id 4 TOULOUSE

Table Intermédiaire (avec traduction) :
- Antoine PARIS Propriétaire
- Antoine TOULOUSE Propriétaire
- Antoine MARSEILLE Locataire
- MARC PARIS Locataire
- MARC TOULOUSE Locataire
- MARC MARSEILLE Propriétaire

Et comme tu vois, tout administré peut être infiniment locataire et propriétaire, sans que personne ne se marche sur les pieds. Pareillement un batiment peut avoir une infinité de propriétaires et locataires A MOINS QUE tu définisses la table intermédiaire une clé UNIQUE (id_batiment propriétaire/locataire). Ainsi si Antoine est Propriétaire de PARIS, Marc ne pourra pas l'etre tant que Antoine l'est, car la contrainte d'unicité veille.

CQFD.

Bon courage.

Petit nouveau ! | 7 Messages

12 juin 2011, 09:33

Qsl mais je me suis endormis sur mon bureau, je vais te montrer une page qui d’après un formulaire des administré on a extrait le locataire mais cette page est comme bottin il ne donne qu'une fiche avec les contacts de la personnes certaines autres informations et le propriétaire du bâtiment. donc la requête est possible, et les profs m'on dit que ct faisable, dans le problème un propriétaire ne peux pas être locataire, il peut juste être propriétaire de 0 à n bâtiments qui contient o à n locataires en tout cas merci
<?php

	include("../commun/params.inc.php");
	$IdAd="";
	$IdBat="";
	$cid="";
	$IdAdm="";
	$retour="";
	$requete="";
$IdBatiment="";
	$enreg="";
	$champs="";
	$valeur="";
	$Nom=""; 
	$Prenom="";
	$Mail="";
	$TelFixe="";
	$TelMobile="";
	$NomProp="";
	$PrenomProp="";
	$AccessCompteurs="";
	$Numero="";
	$Voie="";
	$TypeVoie="";
	if(isset($_POST["IdAdm"])){
		$IdAdm=$_POST["IdAdm"];
		$cid=mysql_connect(MYSQL_SERVER,MYSQL_LOGIN,MYSQL_PASSWORD) or die(mysql_error());
		mysql_select_db(MYSQL_DATABASE,$cid) or die(mysql_error());
		// extraction des données du locataire et du bâtiment
		$requete="select a.IdBat as IdBat,a.IdAdm as IdAdm,a.TelFixe as TelFixe,a.TelMobile as TelMobile,a.Mail as Mail,
				b.Numero as Numero,b.AccesCompteurs as AccessCompteurs,
				v.Voie as Voie,
				t.TypeVoie as TypeVoie
			from TAdministres as a,TBatiments as b,TVoies as v,TTypesVoie as t
			WHERE b.IdBatiment=a.IdBat && v.IdVoie=b.IdVoie && t.IdTypeVoie=v.IdTypeVoie
			&& IdAdm='$IdAdm';";
			$retour=mysql_query($requete,$cid)  or die(mysql_error());
			$enreg=mysql_fetch_array($retour);
			foreach($enreg as $champ=>$valeur)
				$$champ=$valeur;
		// extraction des données du propriétaire
		$requete="select a.Nom as NomProp,a.Prenom as PrenomProp
		from TAdministres as a,TBatiments as b
		where a.IdAdm=b.IdProprietaire && b.IdBatiment='$IdBat'
		;";
			$retour=mysql_query($requete,$cid)  or die(mysql_error());
			$enreg=mysql_fetch_array($retour);
			foreach($enreg as $champ=>$valeur)
				$$champ=$valeur;				
				
	}
?>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">



<title>Document sans titre</title>

<style type="text/css">
.calque {
	font: 14px Verdana, Geneva, sans-serif;
	color: #000;
	-moz- background-color:rgba(255,255,235,0.8);
    -moz- border-radius:10px;
	-moz-border-radius:10px;
	-moz-box-shadow: 10px 10px 8px rgba(0,0,0,0.2);
	-moz-box-shadow: 10px 10px 8px rgba(0,0,0,0.2);
	border-style:solid;
	border-width:1px;
	border-top-color:#d0d0d0;
	border-left-color:#d0d0d0;
	border-right-color:#606060;
	border-bottom-color:#606060;
	background: #CCC;
	background: #CCC;
	margin-right: auto;
	margin-left: auto;
	width: 400px;
	position:relative;
}
#form1{
	top:50px;
}
#affichage{
	top:100px;
	
}
	
	

</style>
<script type="text/javascript">
	function traitement(){
		if(document.getElementById("IdAdm").value!="")
			document.forms["f1"].submit();
		else
			alert("Choisissez d'abord une fiche");
	}
</script>
<script src="SpryAssets/SpryMenuBar.js" type="text/javascript"></script>
<link href="SpryAssets/SpryMenuBarHorizontal.css" rel="stylesheet" type="text/css">
</head>

<body>
<?php include("../php/menuinclude.php")?>;

<div id="form1" class="calque">
<form action="requeteAdresse.php" method="post" enctype="multipart/form-data" name="f1" id="f1">
<label>
  <div align="center">fiche recherchée  </div>
</label>
<br>
<br>
<div align="center">
 <select id="IdAdm" name="IdAdm" onchange="javascript:traitement();">
	<option value="">Choisissez une personne</option>
	<?php
		$cid=mysql_connect(MYSQL_SERVER,MYSQL_LOGIN,MYSQL_PASSWORD) or die(mysql_error());
		mysql_select_db(MYSQL_DATABASE,$cid) or die(mysql_error());
		$requete="select IdAdm,Nom,Prenom FROM TAdministres order by Nom,Prenom;";
		$retouradm=mysql_query($requete,$cid);
		 mysql_close($cid);
		    while($enreg=mysql_fetch_array($retouradm)){
			foreach($enreg as $champ=>$valeur)
				$$champ=$valeur;
				echo "<option value='$IdAdm'>$Nom $Prenom</option>";
			}
	?>
 </select>
</div>
<br>
<br>

</div>
</form>
</div>
<div class="calque" id="affichage">
	
	Adresse : <?php echo "$Numero $TypeVoie $Voie";?>
	<br>
	Mail : <?php echo "$Mail";?>
	<br> 
	Fixe : <?php echo "$TelFixe";?>
	<br> 
	Portable : <?php echo "$TelMobile";?>
	<br>
	Accés compteurs : <?php echo ($AccessCompteurs)?"Public":"Prive";?>
	<br>
	Propriétaire : <?php echo "$NomProp $PrenomProp";?>
	<br>
</div>
</body>
</html>

Petit nouveau ! | 7 Messages

12 juin 2011, 15:23

J'ai failli crier quand j'ai vu la référence croisée, mais ton explique aide. Donc, effectivement, il n'y pas de référence croisée (sauf dans ton schéma ^^), mais je vais t'aider en te posant une question :
j'ai remis des tables avec des explications

Comment fais-tu si tu considères que un propriétaire peut avoir plusieurs batiments ? Bien sûr, tu vas me dire que plusieurs FK de batiment peuvent pointer sur le propriétaire. Ok.

Comment fais-tu si un locataire loue ... En fait. Je n'ai pas fini ma question que je suis déjà perdu. les deux tables forme une sorte de cercle, et au final, on ne sait pas bien qui fait qui avec quoi. Question qui va te faire changer de schéma : Si un propriétaire de 2 batiments est aussi locataire de 2 autres, comment ça va se dégoupillé. Ce sera impossible. En re-réfléchissant même un simple propriétaire de 2 batiments, c'est impossible. Mais tu vois, rien que le fait que ce soit si difficile pour moi d'imaginer avec le schéma le détruit.

Il y a donc d'après moi deux points importants qui vont jouer sur la conception :

- Il faut une relation n:m entre batiments et locataires ou 1:n si un batiment n'a pas plusieurs locataires possibles. Pareils pour les propriétaires.
- Il faut définir quel rôle représente la relation entre batiment et locataire/propriétaire, puisque ta table des administrés est trop large.

je te propose donc de rajouter une table intermédiaire, qui aura une clé primaire, une référence au batiment, une référence à l'administré, et un role : locataire ou propriétaire.

Par exemple

Administrés :
- id 5 Antoine
- id 7 Marc

Batiments :
- id 2 PARIS
- id 3 MARSEILLE
- id 4 TOULOUSE

Table Intermédiaire (avec traduction) :
- Antoine PARIS Propriétaire
- Antoine TOULOUSE Propriétaire
- Antoine MARSEILLE Locataire
- MARC PARIS Locataire
- MARC TOULOUSE Locataire
- MARC MARSEILLE Propriétaire

Et comme tu vois, tout administré peut être infiniment locataire et propriétaire, sans que personne ne se marche sur les pieds. Pareillement un batiment peut avoir une infinité de propriétaires et locataires A MOINS QUE tu définisses la table intermédiaire une clé UNIQUE (id_batiment propriétaire/locataire). Ainsi si Antoine est Propriétaire de PARIS, Marc ne pourra pas l'etre tant que Antoine l'est, car la contrainte d'unicité veille.

CQFD.

Bon courage.

Petit nouveau ! | 7 Messages

12 juin 2011, 15:30

Bonjour,

Votre Site est magnifique, quelle maîtrise des CSS et du javaScript/ je vous envie/

bien à vous
Aliénor

devlop78
Invité n'ayant pas de compte PHPfrance

12 juin 2011, 18:16

Au fait, je n'y ai pensé qu'à 5h du matin en me couhant :

- Si tu pars du principe que un batiment a 1 forcément un propriétaire
- Si tu pars du principe que un batiment a 0 ou 1 forcément locataire

La structure est beaucoup plus simple :

Tu as une table administrés
Tu as une table batiments avec deux Fk :

- un FK id_proprietaire NOT NULL
- un FK id_locataire NULL

Les deux FK pointant sur la table administré et sur la PK de cette dernière, mais marquant le rôle.
Par contre, c'est beaucoup moins souple, mais pour le coup ça a l'avantage d'obliger à lier un batiment à un propriétaire.

A coté, plein de choses sont possibles : une table intermédiaire juste pour les locataires, avec des dates pour faire un historique des locations, et des champs uniques pour bien rendre cohérentes les choses.

devlop78
Invité n'ayant pas de compte PHPfrance

12 juin 2011, 19:12

Bonjour,

Votre Site est magnifique, quelle maîtrise des CSS et du javaScript/ je vous envie/

bien à vous
Aliénor

Merci. Par contre, il y a très peu de CSS ... Ce sont surtout des images, donc quelle maitrise de photoshop !! ^^

Petit nouveau ! | 7 Messages

13 juin 2011, 00:18

Bonsoir,
Oui vous avez raison, et j'aimerai savoir la syntaxe de la requête jai remis des explications sur le lien des tables, je crois que vous tenez la solution, mais comment l'écrire, j'ai essayé des tas de combinaisons, mais rien, il manque tjrs les propriétaires, je vous mets un script ou il y a le meme style de requête mais pour une seule personne, j'essaie d'indenter et d'enlever le javaScript et les links qui n'apporteraient rien de plus.

Exemple :je choisis une nom prénom et j'obtiens toutes les informations dont le propriétaire de la personne ce script fonctionne,
et la j'ai besoin de la listes propriétaires locataires classés par rue.
<?php

	include("../commun/params.inc.php");
	$IdAd="";
	$IdBat="";
	$cid="";
	$IdAdm="";
	$retour="";
	$requete="";
        $IdBatiment="";
	$enreg="";
	$champs="";
	$valeur="";
	$Nom=""; 
	$Prenom="";
	$Mail="";
	$TelFixe="";
	$TelMobile="";
	$NomProp="";
	$PrenomProp="";
	$AccessCompteurs="";
	$Numero="";
	$Voie="";
	$TypeVoie="";
	if(isset($_POST["IdAdm"])){
		$IdAdm=$_POST["IdAdm"];
		$cid=mysql_connect(MYSQL_SERVER,MYSQL_LOGIN,MYSQL_PASSWORD) or die(mysql_error());
		mysql_select_db(MYSQL_DATABASE,$cid) or die(mysql_error());
		// extraction des données du locataire et du bâtiment
		$requete="select a.IdBat as IdBat,a.IdAdm as IdAdm,a.TelFixe as TelFixe,a.TelMobile as TelMobile,a.Mail as Mail,
				b.Numero as Numero,b.AccesCompteurs as AccessCompteurs,
				v.Voie as Voie,
				t.TypeVoie as TypeVoie
			from TAdministres as a,TBatiments as b,TVoies as v,TTypesVoie as t
			WHERE b.IdBatiment=a.IdBat && v.IdVoie=b.IdVoie && t.IdTypeVoie=v.IdTypeVoie
			&& IdAdm='$IdAdm';";
			$retour=mysql_query($requete,$cid)  or die(mysql_error());
			$enreg=mysql_fetch_array($retour);
			foreach($enreg as $champ=>$valeur)
				$$champ=$valeur;
		// extraction des données du propriétaire
		$requete="select a.Nom as NomProp,a.Prenom as PrenomProp
		from TAdministres as a,TBatiments as b
		where a.IdAdm=b.IdProprietaire && b.IdBatiment='$IdBat'
		;";
			$retour=mysql_query($requete,$cid)  or die(mysql_error());
			$enreg=mysql_fetch_array($retour);
			foreach($enreg as $champ=>$valeur)
				$$champ=$valeur;				
				
	}
?>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>

<body>
<?php include("../php/menuinclude.php")?>;
<div id="form1" class="calque">
<form action="requeteAdresse.php" method="post" enctype="multipart/form-data" name="f1" id="f1">
<label>
  <div align="center">fiche recherchée  </div>
</label>
<br>
<br>
<div align="center">
 <select id="IdAdm" name="IdAdm" onchange="javascript:traitement();">
	<option value="">Choisissez une personne</option>
	<?php
		$cid=mysql_connect(MYSQL_SERVER,MYSQL_LOGIN,MYSQL_PASSWORD) or die(mysql_error());
		mysql_select_db(MYSQL_DATABASE,$cid) or die(mysql_error());
		$requete="select IdAdm,Nom,Prenom FROM TAdministres order by Nom,Prenom;";
		$retouradm=mysql_query($requete,$cid);
		 mysql_close($cid);
		    while($enreg=mysql_fetch_array($retouradm)){
			foreach($enreg as $champ=>$valeur)
				$$champ=$valeur;
				echo "<option value='$IdAdm'>$Nom $Prenom</option>";
			}
	?>
 </select>
</div>
<br>
<br>

</div>
</form>
</div>
<div class="calque" id="affichage">
	
	Adresse : <?php echo "$Numero $TypeVoie $Voie";?>
	<br>
	Mail : <?php echo "$Mail";?>
	<br> 
	Fixe : <?php echo "$TelFixe";?>
	<br> 
	Portable : <?php echo "$TelMobile";?>
	<br>
	Accés compteurs : <?php echo ($AccessCompteurs)?"Public":"Prive";?>
	<br>
	Propriétaire : <?php echo "$NomProp $PrenomProp";?>
	<br>
</div>
</body>
</html>

devlop78
Invité n'ayant pas de compte PHPfrance

13 juin 2011, 19:03

Je n'ai pas le temps là j'ai une échéance à respecter et je n'ai pas le temps.

Mais juste un conseil, plutot que de déclarer
$machin = '';

// Je fais ma requête

$$champ = $valeur
Tu devrais tout simplement utiliser le tableau ou l'objet que te fournis l'interface mysqli ou PDO.

PDO en mode fetch_objet, te renverra avec la méthode PDOStatement::fetchAll() un tableau contenant chaque ligne sous forme d'objet.

Ainsi tu peux faire
//requête
$lignes = $request->fetchAll();

echo '<table>';
foreach ($lignes as $ligne)
{
 echo "<tr><td>{$ligne->nom}</td>{$ligne->telephone}</td></tr>";
}
echo '</table>';
Par exemple ;) Ca t'enlevera la moitié de ton code déjà.