Page 1 sur 2

Valeurs multiple pour une colonne d'un SELECT

Posté : 26 août 2005, 11:53
par jeannot1974
Bonjour,

voila mon petit souci, qui a priori peut paraitre simple/
J'ai 3 tables : A, B et C
- la table A contient une clé CA
- la table B contient une clé CB
- la table C contient un ensemble de tuples, formant des couples de valeurs CA et CB

Voici un exemple d'ensemble de valeurs que je peux avoir dans la table C :
CA - CB
---------
1 - 1
1 - 2
1 - 3
2 - 1
2 - 3
Je souhaite, en une seule requête, avoir un résultat de la forme :
1 - 1,2,3
2 - 1,3

Est-ce que quelqu'un aurait une idée de la syntaxe de la requête ?
Pour l'instant, ma requête ne me renvoie en fait que la première valeur de la liste, soit :
1 - 1
2 - 1

Merci pour votre aide précieuse.

Jeannot

Posté : 26 août 2005, 12:07
par ouckileou
et si tu nous donnais la requête que tu as pour l'instant ? ;)

Posté : 26 août 2005, 12:07
par iclo
Il te suffit de faire un simple select.

C'est lors de l'affichage que tu vas gêrer ça, avec une rupture de séquence dans la boucle qui effetuera l'affichage:
Si la valeur CA est différente de la valeur précédente, tu commences une nouvelle ligne et tu affiches CA.

Maintenant tout dépend de ce que tu veux faire exactement

Posté : 26 août 2005, 12:15
par Jeannot1974
Concernant la rupture en afficahge, ça je sais faire...

Mon souci, c'est que pour des raisons "techniques" de production d'une feuille Excel, je dois faire cela en une seule requête.

Je ne peux pas faire un SELECT, le parcourir, et faire ensuite un autre SELECT en fonction de la valeur du moment...

Donc cette solution n'est pas possible... Merci quand même...

Je vais expurger ma requête actuelle des données sensibles et je la posterai de retour de ma pause déjeuner... A tout de suite...

Posté : 26 août 2005, 12:18
par iclo
Je n'ai pas parler de faire plusieurs select, mais d'utiliser une rupture de séquence( avec un test à chaque itération)

Posté : 26 août 2005, 13:58
par Jeannot1974
Ah, tu m'interesses... quel "gueule" ça a ta solution ?

PS : Je prépare ma requête, et la poste dans la foulée...

Posté : 26 août 2005, 14:07
par Jeannot1974
Donc voici la requête "expurgée" :

Code : Tout sélectionner

SELECT A.Code_A as 'CodeTableA', B.Nom_ChampB as 'LibelleTableB', FROM TableA A LEFT JOIN TableC C ON (A.Code_A = C.Code_C) LEFT JOIN TableB B ON (C.Code_C = B.Code_B) WHERE A.Code_A = #valeur#
Voila voila...
(désolé pour le délai, mais le poste de dév, et celui d'accès au net ne sont pas connectés...)

Posté : 26 août 2005, 16:36
par iclo
si tu récupère un result set qui ressemble à ceci :
A B
1 1
1 2
1 3
1 4
2 1
2 2
2 3
2 4

et que tu veux arriver à ceci
1 : 1,2,3,4
2 : 1,2,3,4

c'est une simple question d'affichage :
En gros ça donne ceci :
$idA ="";
while ($resultat = mysql_fetch_array($req)){
   // si c'est un nouveau codeA, on passe à la ligne et on l'affiche 
   if ($id !=  $resultat['CodeTableA']) {
       print "<br>".$resultat['CodeTableA']." : ";
       $id =$resultat['id'];
    }
    print " ".$resultat['CodeTableB'];
}     
J'ai pas eu le temps de tester, mais l'idée doit y être :D :D
Tu devras surement adapter un peu...

Posté : 26 août 2005, 16:45
par Jeannot1974
OK, je fais quelques tests et je te tiens au courant...

Merci...

Posté : 26 août 2005, 16:58
par Augure
Salut,

Le SQL est incapable de faire de l'itératif pur (c'est à dire se rappeller lui même, ou dans notre cas concaténer par ligne n colonnes à la suite avec n différent d'une ligne à l'autre)

Par contre on peut tricher un peu si tu connais le nombre max d'itération que tu peux avoir. Dans notre cas, y a t il un nombre max de CB par CA ?

Voici un exemple de la solution à la quelle je pense. Dans cette exemple on suppose qu'il y a 3 niveau max

Code : Tout sélectionner

Select C.CA, Case count(*) when 1 then ( Select C2.CB From C2 Where C2.CA=C.CA LIMIT 0 TO 1 ) when 2 then ( Select C2.CB From C2 Where C2.CA=C.CA LIMIT 0 TO 1 ) +( Select C2.CB From C2 Where C2.CA=C.CA LIMIT 1 TO 2 ) when 3 then ( Select C2.CB From C2 Where C2.CA=C.CA LIMIT 0 TO 1 ) +( Select C2.CB From C2 Where C2.CA=C.CA LIMIT 1 TO 2 ) +( Select C2.CB From C2 Where C2.CA=C.CA LIMIT 2 TO 3 ) else 'etc ....' end From C Group By C.CA
PS : Attention le couple AB est toujours unique, donc tu ne peux pas afficher A.Code_A as 'CodeTableA'
et à la fois B.Nom_ChampB as 'LibelleTableB'

PS : cette syntaxe fonctionne sur la base SYBASE ASE. Je ne l'ai pas porté sur MySQL. Mais "Cas When Then Else End" existe sous MySQL t il un nombre max de 1,2,3, .... ?

Posté : 26 août 2005, 17:00
par Augure
Heu .... si la réponse doit être en SQL pur c'est moi qui ai raison. Si tu veux que se soit simple .... j'ai tout faux. Prends la solution PHP ;-)

Posté : 26 août 2005, 17:12
par Jeannot1974
Bon en fait ça colle pas avec mon besoin...

La raison pour laquelle je souhaite que cela se fasse dans UNE SEULE REQUETE SQL, est simple, c'est pour générer un fichier XLS ayant en entrée UNE SEULE REQUETE et non pas UNE FONCTION....

Ci-après la dite fonction :
function export_XLS($req, $Fnm, $db) {
		//include("fct_nettoiexls.php");	
		nettoie_XLS();
		// Calcul la date et l'heure de génération du fichier EXCEL
		$date = date("Ymd-His");
		// Composition du nom unique du fichier EXCEL
		$Fnm = "export/".$date."_".$Fnm;
		//$Fnm = "export/".$Fnm;
		
		if (file_exists($Fnm)) {  
	  		unlink($Fnm);
	  	}
		// Ouverture du fichier en ecriture
		$inF = fopen($Fnm,"w+");
		
		fputs($inF,"<table border='1'>\n");
			
		if ($req) {
			$res = mysql_db_query($db,$req) or die ("MESSAGE d'ERREUR : ".mysql_error(). " - ".$req);
			$i = 0;
			
			//Construction de l'entete du tableau
			$chaine = "<tr bgcolor='#EECC11'>";
			while ($i < mysql_num_fields($res)) {
				$meta = mysql_fetch_field($res, $i);
				if (!$meta) {
					echo "Aucun champ n'est disponible<br>\n";
				}
				$chaine .= "<th>".$meta->name."</th>";
				$i++;
			}
			$chaine .= "</tr>";
			fputs($inF,$chaine);
			
			while ($row = mysql_fetch_array($res)) {
				$chaine = "<tr>";
				for ($i=0 ; $i < mysql_num_fields($res) ; $i++) {
					$chaine .= "<td>".$row[$i]."</td>";	
				}
				$chaine .= "</tr>\n";
				fputs($inF,$chaine);
			}
		}
		else {
			echo "Aucune requête n'a été spécifiée...";
		}
		fputs($inF,"</table>");

		fclose($inF);
		
		return $Fnm;
	}
Aux vus de ce code, tu comprends bien, qu'il est difficile (voire impossible d'adopter ta solution (qui est très bonne cependant)).

Bref, c'est pas encore ça, mais on progresse... En fait la soluce serait de faire une boucle au niveau des champs du SELECT, mais c'est pas possible, donc faut trouver une autre solution...

Je suis sur une autre piste, et je te tiendrais au courant si j'ai la solution...

Réponse à AUGURE

Posté : 26 août 2005, 17:17
par Jeannot1974
Ta solution collerai un peu plus avec mon besoin... j'examine la chose...

Merci

Posté : 26 août 2005, 17:20
par Augure
Sinon, tu peux ré écrire une fonction d'export vers XLS qui prend en paramétre un tableau à 2 dimensions. Cette fonction pourrait être ré utilisé pour tes autres requêtes complexe.

Posté : 26 août 2005, 17:20
par iclo
Désolé mais il y a un truc qui me chiffone : je ne comprends où est le problême d'interger une rupture de séquence dans le 2ème while ??