Valeurs multiple pour une colonne d'un SELECT

jeannot1974
Invité n'ayant pas de compte PHPfrance

26 août 2005, 11:53

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

Modérateur PHPfrance
Modérateur PHPfrance | 6373 Messages

26 août 2005, 12:07

et si tu nous donnais la requête que tu as pour l'instant ? ;)

ViPHP
ViPHP | 2144 Messages

26 août 2005, 12:07

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

Jeannot1974
Invité n'ayant pas de compte PHPfrance

26 août 2005, 12:15

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...

ViPHP
ViPHP | 2144 Messages

26 août 2005, 12:18

Je n'ai pas parler de faire plusieurs select, mais d'utiliser une rupture de séquence( avec un test à chaque itération)

Jeannot1974
Invité n'ayant pas de compte PHPfrance

26 août 2005, 13:58

Ah, tu m'interesses... quel "gueule" ça a ta solution ?

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

Jeannot1974
Invité n'ayant pas de compte PHPfrance

26 août 2005, 14:07

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...)

ViPHP
ViPHP | 2144 Messages

26 août 2005, 16:36

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...
Modifié en dernier par iclo le 26 août 2005, 16:46, modifié 1 fois.

Jeannot1974
Invité n'ayant pas de compte PHPfrance

26 août 2005, 16:45

OK, je fais quelques tests et je te tiens au courant...

Merci...

Eléphant du PHP | 91 Messages

26 août 2005, 16:58

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, .... ?

Eléphant du PHP | 91 Messages

26 août 2005, 17:00

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 ;-)

Jeannot1974
Invité n'ayant pas de compte PHPfrance

26 août 2005, 17:12

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...

Jeannot1974
Invité n'ayant pas de compte PHPfrance

26 août 2005, 17:17

Ta solution collerai un peu plus avec mon besoin... j'examine la chose...

Merci

Eléphant du PHP | 91 Messages

26 août 2005, 17:20

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.
Modifié en dernier par Augure le 26 août 2005, 17:20, modifié 1 fois.

ViPHP
ViPHP | 2144 Messages

26 août 2005, 17:20

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 ??