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 ?

35
demandé sur daveslab 2011-09-09 02:05:26

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
34
répondu Ollie 2011-09-09 08:54:32

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

15
répondu ozmike 2017-05-23 10:31:39
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
5
répondu Michal Satny 2013-03-06 10:24:54
select group_id, 
       listagg(name, ',') within group (order by name) as names
       over (partition by group_id)   
from demotable
group by group_id 
2
répondu PJA 2013-09-25 10:09:25

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
0
répondu marko 2012-05-14 22:47:03

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;
0
répondu Felypp Oliveira 2014-12-16 19:56:06

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

0
répondu zia 2015-01-23 08:18:14