Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
Pages : 1
#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
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='{}'
);
Julien.
https://rjuju.github.io/
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
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
Dernière modification par Geo-x (10/06/2013 08:25:16)
Hors ligne
Pages : 1