Page 1 sur 2

n'arrive pas a faire affiché certaine informations liés à de

Posté : 02 oct. 2007, 10:53
par kweb
Bonjour tous le monde !

Je n'arrive pas a faire affiché certaine informations liés à deux tables.

J'ai deux tables "FORMATION" & "CATEGORIE" - (Formation est lié catégorie)

Code : Tout sélectionner

-- Structure de la table `categorie` -- CREATE TABLE `categorie` ( `id_categorie` int(11) NOT NULL auto_increment, `txt_categorie` varchar(250) NOT NULL, KEY `id_categorie` (`id_categorie`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=23 ; -- -------------------------------------------------------- -- -- Structure de la table `formation` -- CREATE TABLE `formation` ( `id_formation` int(11) NOT NULL auto_increment, `id_categorie_formation` int(11) NOT NULL, `nom_formation` varchar(250) NOT NULL, `date_formation` date NOT NULL, `ville_formation` varchar(250) NOT NULL, `pays_formation` varchar(250) NOT NULL, `publique_formation` longtext NOT NULL, `objectif_formation` longtext NOT NULL, `description_formation` longtext NOT NULL, `program_formation` longtext NOT NULL, KEY `id_formation` (`id_formation`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=16 ;
Une "FORMATION" est toujours lié à une "CATEGORIE" (j'ai donc mis un champs "id_categorie_formation" dans la table "formation" pour récupérer l'id de la table catégorie)

Ce que je souhaite faire
Faire afficher toutes les formations lié a chaque catégorie existante

Ce que j'ai déjà réalisé
Affiché toute les catégorie
$sql = "SELECT txt_categorie FROM categorie";
$sql_retour =  mysql_query ($sql) or die (mysql_error());

while ($ligne = mysql_fetch_array($sql_retour))
			{	
			// CREATION d'un tableau
				echo '<table width="100%" border="0" cellspacing="1" cellpadding="0">';
				
				echo '<tr>';
				echo '<td colspan="5" id="recherche_date">';
				
			// Cellule NOM FORMATION
				echo '<span class="smallredtext">'.$ligne['txt_categorie'].'</span>' ;
				echo '</td>';
				echo '</tr>';
				
			// CREATION d'une deuxieme Lignes
				echo '<tr>';
				
			//Titre des cellules
				echo '<td width="20">&nbsp;</td>';
				echo '<td id="descriptif_Titre"><strong>Formation</strong></td>';
				echo '<td id="descriptif_Titre"><strong>date</strong></td>';
				echo '<td id="descriptif_Titre"><strong>Ville</strong></td>';
				echo '<td id="descriptif_Titre">&nbsp;</td>';
					
			// Fin de la deuxième Ligne
				echo '</tr>';

ensuite, c'est la ou est mon problème, je veux affiché toutes les formations associé à une catégorie.
donc a la suite du code précédent j'ai mis :
// SELECTIONNER toute les donnée de la table formation et catégorie
				$themes = $ligne['id_categorie'];
				$sql2 = "SELECT *			
						FROM formation 
						WHERE id_categorie_formation = $themes 
						ORDER BY nom_formation ASC
						";
			$sql2_retour =  mysql_query($sql) or die (mysql_error());
				
			while ($affiche = mysql_fetch_array($sql2_retour))
				{ 
				// CREATION d'une troisieme Ligne
					echo "<tr>";
				
				// Cellule 
					echo '<td>';
					echo '&nbsp;';
					echo '</td>';	
				
				// Cellule NOM DE LA FORMATION
					echo '<td id="descriptif">';
					echo ucfirst(substr($affiche['nom_formation'],0,30));
					echo '</td>';
				
				// Cellule THEMES
					echo '<td id="descriptif">';
					echo ucfirst($ligne['date_formation']) ;
					echo '</td>';
				
				// Cellule THEMES
					echo '<td id="descriptif">';
					echo ucfirst($ligne['ville_formation']) ;
					echo '</td>';
					
					
				// Cellule + DE DETAIL
					echo '<td id="descriptif">';
					echo '<a href="programme_date.php?details='.$ligne['id_formation'].'" class="smallgraytext"><img src="images/detail.gif" alt="D&eacute;tails de la formation" width="53" height="15" border="0" /></a>' ;
					echo '</td>';
	
				// FIN de la troisieme ligne
				echo '</tr>';
				}
			// FIN du tableau
				echo '</table><p></p><br />';
	}		
Le résultat à l'affichage
le résultat n'est pas du tout ce que j'attendais, il ne m'affiche pas le nom, date et ville des formations, et surtout j'ai 5 lignes vide qui corresponde en faite au nombre de catégorie existante.

J'ai donc besoin de votre aide.
merci de votre participation

Posté : 02 oct. 2007, 11:05
par iclo
Il vaut nettement mieux tout faire avec une seule requette, qui récuperera les informations sur les deux tables, ça évitera de surcharger le serveur de base donnée (si il y beaucoup de catégories, ça devient vite lourd)

Code : Tout sélectionner

SELECT * FROM formation f, categorie c WHERE f.id_categorie_formation = c.id_categorie ORDER BY nom_formation ASC

Une seule boucle permet d'obtenir l'affichage que tu recherches à avoir.
Il suffit d'afficher les informations sur la catégorie, si elles ont changé par rapport à l'enregistrement précédent.
A la grosse louche cela ressemblerait à çà:
$id_categorie = 0;
while ($affiche = mysql_fetch_array($sql)){
   if ($affiche['id_categorie'] != $id_categorie){
      // affichage info catégorie
   }
   $id_categorie == $affiche['id_categorie']
   // affichage des infos de la formation
}

Posté : 02 oct. 2007, 11:22
par kweb
Ok, par contre juste une petite précision ?
SELECT * FROM formation f, categorie c
WHERE f.id_categorie_formation = c.id_categorie
ORDER BY nom_formation ASC
Que signifie la lettre "f" et "c", pourquoi ne pas mettre "*"

merci

Posté : 02 oct. 2007, 11:27
par iclo
f et c sont des alias pour les tables.
Dans le where : f.id_categorie_formation indique qu'on prend le champ de la table formation et c.id_categorie : le champ id_categorie de la table catégorie. C'est surtout utile, si deux tables ont chacun un champ du même nom, ça permet de les distingués.

ps: dans le select, il vaut mieux éviter l'* qui fait rappatrier tous les champs, et définir quels sont les champs qu'on a besoin de récupérer:
select c.id_categorie, f.id_categorie_formation, ...

Posté : 02 oct. 2007, 15:42
par kweb
Je suis désolé, mais je galère toujours. #-o
Dans la solution que tu ma suggérer, l'affichage ne se fais pas comme je le souhaite.
je ne dis pas que ce que tu as dit est faux, c'est peut êtres moi qui est mal écrit la syntax :lol:

Quelques exemple pour mieux me comprendre :

Thème existant en BD:
Médecin
chirurgien
Ostéopathe
Formation existante en BD lié avec un thème :
formation 1 (chirurgien)
formation 2 (chirurgien)
formation 3 (chirurgien)
formation 4 (médecin)
Affichage souhaité :
Médecin
- formation 4

Chirurgien
- formation 1
- formation 2
- formation 3
La thème "ostéopathe" n'apparait pas car il n'y a aucune formation.
les autres thèmes apparaissent une fois (et non pas plusieurs fois) pour lister les formations lié.

Posté : 02 oct. 2007, 18:10
par Tracker
C'est normal le produit cartésien est un join strict...
Dans ton cas tu dois utiliser un join "à gauche":

Code : Tout sélectionner

SELECT * FROM categorie c left join formation f on f.id_categorie_formation = c.id_categorie ORDER BY c.txt_categorie ASC
Le join strict vire les informations ne validant pas le critère.

Posté : 03 oct. 2007, 11:37
par kweb
Je viens de tester cette syntaxe, mais l'affichage ne correspond pas a ce que je souhaite #-o #-o #-o

$sql=mysql_query("
				SELECT 
				txt_categorie, nom_formation, ville_formation, date_formation
				
				FROM 
				formation 
				
				LEFT JOIN 
				categorie 
				
				ON categorie.id_categorie = formation.id_categorie_formation 
				
				ORDER BY 
				txt_categorie
				
				") or die(mysql_error());

//on initialise une variable
$categorie_precedente='';
while($resultat=mysql_fetch_assoc($sql)) 
	{
	if($resultat['txt_categorie']!=$categorie_precedente) echo $resultat['txt_categorie'].'<br />';
	echo ' - '.$resultat['nom_formation'].' - '.$resultat['date_formation'].' - '.$resultat['ville_formation'].'<br /><br />';
	
	//on met à jour $categorie_precedente
	$categorie_precedente = $resultat['categorie'];
	}
Peut on utiliser un "DISTINCT" lorsque il y a plusieurs champs sélectionner ?
J'AI VRAIMENT besoin de trouvé une solution a mon problème......
Merci pour votre aide

Posté : 03 oct. 2007, 11:39
par iclo
Qu'obtiens tu avec la dernière version de ton code et qu'est ce que tu souhaites obtenir ?

Posté : 03 oct. 2007, 11:52
par kweb
Si l'on reste basé sur ce modèle :
Thème existant en BD:
Médecin
chirurgien
Ostéopathe
Formation existante en BD lié avec un thème :
formation 1 => lié au thème: chirurgien
formation 2 => lié au thème: chirurgien
formation 3 => lié au thème: chirurgien
formation 4 => lié au thème: médecin
Voici le résultat obtenu sur la dernière syntaxe que j'ai écrite :
Chirurgien
- formation 1
-------------------
Chirurgien
- formation 2
-------------------
Chirurgien
- formation 3
-------------------
Médecin
- formation 4
Et voici le résultat que je voudrais obtenir :
Chirurgien
- formation 1
- formation 2
- formation 3
-------------------
Médecin
- formation 4
L'explication est elle claire ?
merci

Posté : 03 oct. 2007, 11:57
par iclo
if ($resultat['txt_categorie']!=$categorie_precedente
Tu effectues ton test pour savoir si tu dois afficher la catégorie sur sur la variable "txt_categorie"
$categorie_precedente = $resultat['categorie'];
Mais tu lui affectes la variable "categorie", et mémorise cette information pour le test suivant

Comme il est probablement que les champs categorie et txt_categorie contiennent des valeurs différentes, le test renvoit toujours vrai et la catégorie est affiché pour chaque ligne.

Posté : 03 oct. 2007, 12:14
par kweb
D'accord !
mais je suis toujours un peu perdu.

effectivement je lui dit :
SI "txt_categorie" est different de la variable "categorie_precedente" (qui est vide) tu affiche "txt_categorie" etc...

par contre, je ne serais pas t'expliquer pourquoi j'ai mis :
$categorie_precedente = $resultat['categorie'];
en faits j'ai fais des mixtes de partie de code que j'ai trouvé sur le net, sans trop avoir la logique :oops:
on vas dire que je faisais des tests.
de plus $resultat['categorie'] n'existe pas étant donnée que dans la BD le champ catégorie n'existe pas.
J'ai donc tester en le mettant en commentaire, est j'ai le même résultat que tous a l'heure ??

pourrais tu m'eguillier un peu plus ?
je te remercie du temps passé pour ce probléme

Posté : 03 oct. 2007, 12:29
par iclo
Bon en résumé, avant que je parte parte manger.
Quelques détails supplémentaires sur le code déja donné.
// initilisation de la variable contenant l'identifiant de la catégorie
$id_categorie = 0;
while ($affiche = mysql_fetch_array($sql)){
   // Si l'identifiant est différent de celui mémoriser, c'est qu'on a une nouvelle catégorie
   if ($affiche['id_categorie'] != $id_categorie){
      // affichage info catégorie
      .....
      // On met à jour la variable qui contient l'identifiant de catégorie
      $id_categorie == $affiche['id_categorie']
   }

   // affichage des infos de la formation
}
L'idée, c'est qu'on mémorise en permanence l'idendifiant de la catégorie.
Au début de l'algorithme, On initialise la variable avec un identifiant 0, qui ne sera pas dans la table, afin de forcer l'affichage de la première catégorie.

Au début de chaque itération, on regarde si la catégorie de l'enregistrement qu'on va afficher, est différente de celui de la ligne précédente.
Si c'est le cas, on a une nouvelle catégorie, on va alors afficher ses informations et mettre à jour la variable qui mémorise l'identifiant de catégorie, pour pouvoir réaliser le test, lors de l'itération suivante.
Ensuite, on affiche les informations sur la formation,

Posté : 03 oct. 2007, 14:51
par kweb
Je te remercie pour ton explication qui est très explicite .
Mais, lorsque je test le tout, je reviens au résultat de tout a l'heure, c'est a dire :
Chirurgien
- formation 1
-------------------
Chirurgien
- formation 2
-------------------
Chirurgien
- formation 3
-------------------
Médecin
- formation 4
le code source lié à cette affichage :
$sql=mysql_query("
				SELECT 
				id_categorie, txt_categorie, nom_formation, id_categorie_formation, ville_formation, date_formation
				
				FROM 
				formation 
				
				LEFT JOIN 
				categorie 
				
				ON categorie.id_categorie = formation.id_categorie_formation 
				
				ORDER BY 
				txt_categorie
				
				") or die(mysql_error());


// initilisation de la variable contenant l'identifiant de la catégorie
$id_categorie = 0;

while ($affiche = mysql_fetch_array($sql))
	{
	// Si l'identifiant est différent de celui mémoriser, c'est qu'on a une nouvelle catégorie
	   if ($affiche['id_categorie'] != $id_categorie)
			{
			// affichage info catégorie
				echo $affiche['txt_categorie'].' <br /><br /> ';
				
			// On met à jour la variable qui contient l'identifiant de catégorie
				$id_categorie == $affiche['id_categorie'];
			}
	// affichage des infos de la formation
	echo ' - '.$affiche['nom_formation'].' - '.$affiche['date_formation'].' - '.$affiche['ville_formation'].'<br />';
	} 
?>
Une question, la requête "DISTINCT", ne pourrais pas me servir pour n'afficher qu'une fois la catégorie ?

J'ai beaux faire de recherche sur le net, je ne trouve aucun cas similaire ?
|*()

Un petit rajout :
n'est il pas possible de partir sur ce que j'avais fais au tout début. c'est a dire que j'arrivais a faire affiché le nom des catégories une seule fois .
$sql = "SELECT DISTINCT c.txt_categorie FROM formation f, categorie c WHERE f.id_categorie_formation = c.id_categorie";
$sql_retour =  mysql_query ($sql) or die (mysql_error());

while ($ligne = mysql_fetch_array($sql_retour))
			{	
			// Cr&eacute;ation d'un tableau
				echo '<table width="100%" border="0" cellspacing="1" cellpadding="0">';
				
				echo '<tr>';
				echo '<td colspan="5" id="recherche_date">';
				
			// Cellule DATE DE LA FORMATION
				echo '<span class="smallredtext">'.$ligne['txt_categorie'].'</span>' ;
				echo '</td>';
				echo '</tr>';
				
			// CREATION d'une deuxieme Lignes
				echo '<tr>';
				
			//Titre des cellules
				echo '<td width="20">&nbsp;</td>';
				echo '<td id="descriptif_Titre"><strong>Formation</strong></td>';
				echo '<td id="descriptif_Titre"><strong>date</strong></td>';
				echo '<td id="descriptif_Titre"><strong>Ville</strong></td>';
				echo '<td id="descriptif_Titre">&nbsp;</td>';
					
			// Fin de la deuxieme Ligne
				echo "</tr>";
et essayé de trouvé la suite du code qui me permettrais d'afficher toutes les formations lié au catégories ?

Posté : 03 oct. 2007, 15:48
par Tracker
Tu confonds ResultSet (résultat de la requête) et présentation HTML des informations.

Dans ton cas le ResultSet contiendra des lignes, chaque ligne correspondant à un cas particulier d'association Catégorie/Formation défini par le joint utilisé dans ta requête.

L'affichage de l'information (sous forme arborescente) n'a plus de rapport avec SQL (oublie Distinct). Tu dois exploiter les informations retournées par ton ResultSet pour générer l'affichage HTML que tu souhaites via PHP, comme te l'a clairement expliqué iclo (stockage de l'ancien txt_categorie, et comparaison avec la valeur courante pour savoir si tu fais une rupture d'affichage ou pas, pour chaque ligne du ResultSet).

Arrête de te torturer avec SQL, la solution n'est pas là !!.

Posté : 03 oct. 2007, 16:50
par kweb
Bon je crois que je vais jeter l'éponge, c'est pas de mon niveau.... sa fais déjà + 24h que je bloque sur ce problème.

Mes derniers tentative ont été d'essayer de faire une condition qui dirais :
SI le nom de la catégorie existe plus d'une fois, on ne l'affiche qu'une fois
et
SI la formation a le même ID que la catégorie, on l'affiche

mais sans succès.
Merci a tous ce qui ont participé a ce POST.