Vous n'êtes pas identifié(e).

#1 05/06/2013 14:09:34

Geo-x
Membre

Sélection et concaténation de champ

Bonjour @ tous,

j'aurais besoin de vos lumières pour résoudre un problème au niveau d'une sélection, je m'explique :

1- J'ai une table qui est formée de la façon suivante :

ID	NOM
1	coucou
2	chouette
1	coucou
2	coucou	
1	chouette
1	chouette

2- Je souhaiterais à partir de cette table sortir une sélection qui me donnerait :

ID	NOM
1	2 x coucou - 2 x chouette
2	1 x coucou - 1 x chouette

3- Pour arriver à ce résultat, j'ai bien tenté de faire un array en l'intégrant à la requête suivante :

SELECT replace(replace(replace(replace(replace(replace(
array(SELECT COALESCE(count("NOM"), 0::bigint)::text ||' x '|| "NOM" AS colonne
FROM table
WHERE table."ID" IS NOT NULL
GROUP BY table."ID",table."NOM" ORDER BY "NOM")::text,',',' - '),'{"','- '),'"',''),'}',''),'{NULL','Pas d''information'),'- NULL','')

4- Mais le problème, c'est qu'avec ce genre de requête j'arrive toujours au résultat suivant :

ID	NOM
1	3 x coucou - 3 x chouette
2	3 x coucou - 3 x chouette

Avez-vous une solution à ce problème?

Geo-x

Hors ligne

#2 05/06/2013 21:34:32

gleu
Administrateur

Re : Sélection et concaténation de champ

Oulala, je ne sais pas comment vous arrivez à une requête comme ça. Décomposez le travail, ce sera plus simple.

En fait, vous devez déjà compter le nombre d'éléments par id et nom. C'est un agrégat qui se fait ainsi :

select id, count(*)::text||' x '||nom as texte from t group by id, nom;

Ça donne le résultat suivant :

 id |    texte     
----+--------------
  1 | 2 x coucou
  1 | 2 x chouette
  2 | 1 x coucou
  2 | 1 x chouette
(4 rows)

On touche au but. Maintenant, on veut agréger les lignes de ce résultat par rapport à l'id, ce qui nous donne :

with tmp as (select id, count(*)::text||' x '||nom as texte from t group by id, nom)
select id, string_agg(texte, ' - ') from tmp group by id;

Et le résultat :

 id |        string_agg         
----+---------------------------
  1 | 2 x coucou - 2 x chouette
  2 | 1 x coucou - 1 x chouette
(2 rows)

Guillaume.

Hors ligne

#3 06/06/2013 09:00:42

Geo-x
Membre

Re : Sélection et concaténation de champ

Bonjour Gleu,

D'abord, merci pour la rapidité de vos interventions et la qualité de vos réponses.

Par rapport à votre commentaire : "Oulala, je ne sais pas comment vous arrivez à une requête comme ça"

Il est vrai que j'ai tendance parfois à chercher le résultat par des requêtes complexes souvent issus d'une méconnaissance de certaines méthodes.

Aujourd'hui, c'est le WITH que je n'ai jamais utilisé en requête (bien que je l'ai déjà vu avec les OID's).

Malheureusement, cette requête ne fonctionne pas :

ERROR: syntax error at or near "WITH tmp"
État SQL :42601
Caractère : 1

Très probablement car ma version de postgres n'est pas compatible avec cette commande : "PostgreSQL 8.3.10, compiled by Visual C++ build 1400"

Il est également à noter que la fonction string_agg() n'existe visiblement pas sous cette version de postgres.

Geo-x

Dernière modification par Geo-x (06/06/2013 09:06:29)

Hors ligne

#4 06/06/2013 10:19:12

kenrio
Membre

Re : Sélection et concaténation de champ

Je sais pas si vous le savez mais la 8.3 n'est plus supporté et migrer serait à mon avis une très bonne solution pour la suite.

Hors ligne

#5 06/06/2013 10:47:15

Geo-x
Membre

Re : Sélection et concaténation de champ

Bonjour kenrio,

Cette remarque est pertinente, et en effet, c'est quelque chose qui est prévu au cours de l'année.

Hors ligne

#6 06/06/2013 11:03:30

kenrio
Membre

Re : Sélection et concaténation de champ

le problème c'est que plus ça va aller plus vous aller voir des fonctions et des outils non compatible avec votre version, mais si c'est prévu tant mieux smile

Hors ligne

#7 06/06/2013 16:42:26

rjuju
Administrateur

Re : Sélection et concaténation de champ

Vous pouvez réécrire la requête ainsi :

select id, array_to_string(array_agg(texte), ' - ') from (
select id, count(*)::text||' x '||nom as texte from t group by id, nom
) tmp
group by id;

Cela nécessite de créer l'aggrégat array_agg qui n'est pas disponible par défaut en 8.3 avec la commande :

CREATE AGGREGATE array_agg(anyelement) (
SFUNC=array_append,
STYPE=anyarray,
INITCOND='{}'
);

Hors ligne

#8 06/06/2013 17:26:16

Geo-x
Membre

Re : Sélection et concaténation de champ

Ca fonctionne à merveille!

Merci pour votre précieuse aide.

Geo-x

Hors ligne

#9 06/06/2013 19:20:12

gleu
Administrateur

Re : Sélection et concaténation de champ

Très probablement car ma version de postgres n'est pas compatible avec cette commande : "PostgreSQL 8.3.10, compiled by Visual C++ build 1400"
Il est également à noter que la fonction string_agg() n'existe visiblement pas sous cette version de postgres.

C'est le genre de problème auquel on s'expose quand on ne donne pas son numéro de version smile


Guillaume.

Hors ligne

#10 10/06/2013 08:25:03

Geo-x
Membre

Re : Sélection et concaténation de champ

C'est le genre de problème auquel on s'expose quand on ne donne pas son numéro de version

Oui Gleu, vous avez tout à fait raison. Mais d'un autre côté, l'avantage, c'est que j'ai appris quelque chose qui me servira sur la version 9.x de postgres wink

Dernière modification par Geo-x (10/06/2013 08:25:16)

Hors ligne

Pied de page des forums