J'ai une table comme celle-ci:
group_id name
-------- ----
1 David
1 John
1 Alan
1 David
2 Julie
2 Charles
Et je veux le résultat suivant:
group_id names
-------- -----
1 'Alan, David, John'
2 'Charles, Julie'
Je peux utiliser la requête suivante:
select group_id,
listagg(name, ',') within group (order by name) as names
from demotable
group by group_id
Pour obtenir ceci (résultat très similaire):
group_id names
-------- -----
1 'Alan, David, David, John'
2 'Charles, Julie'
Des idées pour filtrer les noms en fonction de l'unicité dans l'appel LISTAGG
?
Je n'ai pas d'instance 11g disponible aujourd'hui, mais vous ne pouvez pas utiliser:
SELECT group_id,
LISTAGG(name, ',') WITHIN GROUP (ORDER BY name) AS names
FROM (
SELECT UNIQUE
group_id,
name
FROM demotable
)
GROUP BY group_id
Super simple réponse - résolu!
select group_id,
regexp_replace(
listagg(name, ',') within group (order by name)
,'([^,]+)(,\1)*(,|$)', '\1\3')
from demotable
group by group_id;
Cela ne fonctionne que si vous spécifiez le délimiteur sur ',' pas ',' c'est-à-dire Ne fonctionne que pour aucun espace après la virgule. Si vous voulez des espaces après la virgule, voici un exemple.
select
replace(
regexp_replace(
regexp_replace('BBall, BBall, BBall, Football, Ice Hockey ',',\s*',',')
,'([^,]+)(,\1)*(,|$)', '\1\3')
,',',', ')
from dual
donne BBall, Football, Hockey sur glace
ma réponse complète ici
create table demotable(group_id number, name varchar2(100));
insert into demotable values(1,'David');
insert into demotable values(1,'John');
insert into demotable values(1,'Alan');
insert into demotable values(1,'David');
insert into demotable values(2,'Julie');
insert into demotable values(2,'Charles');
commit;
select group_id,
(select listagg(column_value, ',') within group (order by column_value) from table(coll_names)) as names
from (
select group_id, collect(distinct name) as coll_names
from demotable
group by group_id
)
GROUP_ID NAMES
1 Alan,David,John
2 Charles,Julie
select group_id,
listagg(name, ',') within group (order by name) as names
over (partition by group_id)
from demotable
group by group_id
En 11g, vous pouvez utiliser la fonction non documentée wm_concat comme ceci:
select wm_concat(distinct name) as names from demotable group by group_id
ci-dessous n'est pas documenté et n'est pas recommandé par Oracle. et ne peut pas appliquer dans la fonction, show error
select wm_concat(distinct name) as names from demotable group by group_id
salutations zia
J'avais besoin de cette paix de code en tant que sous-requête avec un filtre de données avant l'agrégation basée sur la requête la plus externe, mais je n'ai pas pu le faire avec le code de réponse choisi car ce filtre doit être placé dans la sélection la plus interne (requête de troisième niveau) et les paramètres de filtre se trouvaient dans la sélection la plus extérieure (requête de premier niveau), ce qui me donnait l'erreur ORA-00904: "TB_OUTERMOST". "COL": identificateur non valide comme le SQL ANSI indique les références de table (noms de corrélation ) sont étendus à un seul niveau.
J'avais besoin d'une solution sans niveaux de sous-requêtes et celle-ci fonctionnait parfaitement pour moi:
with
demotable as
(
select 1 group_id, 'David' name from dual union all
select 1 group_id, 'John' name from dual union all
select 1 group_id, 'Alan' name from dual union all
select 1 group_id, 'David' name from dual union all
select 2 group_id, 'Julie' name from dual union all
select 2 group_id, 'Charlie' name from dual
)
select distinct
group_id,
listagg(name, ',') within group (order by name) over (partition by group_id) names
from demotable
-- where any filter I want
group by group_id, name
order by group_id;