Comment utiliser la fonction LISTAGG D'Oracle avec un filtre unique? [dupliquer]
cette question a déjà une réponse ici:
- LISTAGG dans Oracle pour retourner des valeurs distinctes 20 réponses
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 le requête suivante:
select group_id,
listagg(name, ',') within group (order by name) as names
from demotable
group by group_id
pour obtenir ce (résultat très similaire):
group_id names
-------- -----
1 'Alan, David, David, John'
2 'Charles, Julie'
Comment puis-je filtrer les noms par unicité dans l'appel LISTAGG
?
7 réponses
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)
,'([^,]+)(,)*(,|$)', '')
from demotable
group by group_id;
Cela ne fonctionne que si vous spécifiez le délimiteur ',' non ', ' ie fonctionne seulement pour aucun espace après la virgule. Si vous voulez des espaces après la virgule - voici un exemple comment.
select
replace(
regexp_replace(
regexp_replace('BBall, BBall, BBall, Football, Ice Hockey ',',\s*',',')
,'([^,]+)(,)*(,|$)', '')
,',',', ')
from dual
donne BBall, Football, Hockey Sur Glace
ma réponse 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
dans 11g, vous pouvez utiliser la fonction sans document wm_concat comme ceci:
select wm_concat(distinct name) as names from demotable group by group_id
j'ai eu besoin de cette paix de code comme un sous-ensemble avec un certain filtre de données avant l'agrégation basée sur la requête la plus externe mais je n'ai pas été en mesure de le faire en utilisant le code de réponse choisi parce que ce filtre devrait aller dans le plus interne select (requête de troisième niveau) et les paramètres de filtre était dans le plus externe select (requête de premier niveau), ce qui m'a donné l'erreur ORA-00904:"TB_OUTERMOST"."COL": identifiant non valide car le SQL ANSI indique que les références de table (noms de corrélation) sont limités à un seul niveau de profondeur.
j'avais besoin d'une solution sans niveaux de sous-traitance et celle-ci ci ci-dessous a bien fonctionné 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;
ci-dessous n'est pas documenté et n'est pas recommandé par oracle. et ne peut pas s'appliquer dans la fonction, Afficher l'erreur
select wm_concat(distinct name) as names from demotable group by group_id
en ce qui concerne zia