it-swarm.com.de

Wie kann ich die LISTAGG-Funktion von Oracle mit einem einzigartigen Filter verwenden?

Ich habe einen Tisch wie diesen:

group_id  name  
--------  ----
1         David
1         John
1         Alan
1         David
2         Julie
2         Charles

Und ich möchte folgendes Ergebnis:

group_id  names
--------  -----
1         'Alan, David, John'
2         'Charles, Julie'

Ich kann die folgende Abfrage verwenden:

select group_id, 
       listagg(name, ',') within group (order by name) as names
from demotable
group by group_id 

Um dieses zu erhalten (sehr ähnliches Ergebnis):

group_id  names
--------  -----
1         'Alan, David, David, John'
2         'Charles, Julie'

Gibt es irgendwelche Ideen, wie ich die Namen im Aufruf von LISTAGG nach Eindeutigkeit filtern kann?

41
daveslab

Ich habe heute keine 11g-Instanz verfügbar, aber Sie könnten Folgendes nicht verwenden:

SELECT group_id,
       LISTAGG(name, ',') WITHIN GROUP (ORDER BY name) AS names
  FROM (
       SELECT UNIQUE
              group_id,
              name
         FROM demotable
       )
 GROUP BY group_id
40
Ollie

Super einfache Antwort - gelöst!

select group_id, 
regexp_replace(
    listagg(name, ',') within group (order by name)
    ,'([^,]+)(,\1)*(,|$)', '\1\3')
from demotable
group by group_id;  

Dies funktioniert nur, wenn Sie das Trennzeichen auf ',' nicht ',' angeben. Wenn Sie nach dem Komma Leerzeichen wünschen, finden Sie hier ein Beispiel wie.

select 
replace(
    regexp_replace(
     regexp_replace('BBall, BBall, BBall, Football, Ice Hockey ',',\s*',',')            
    ,'([^,]+)(,\1)*(,|$)', '\1\3')
,',',', ') 
from dual

gibt BBall, Fußball, Eishockey 

meine vollständige Antwort hier

15
ozmike
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
Michal Satny
select group_id, 
       listagg(name, ',') within group (order by name) as names
       over (partition by group_id)   
from demotable
group by group_id 
2
PJA

In 11g können Sie die undokumentierte Funktion wm_concat folgendermaßen verwenden:

     select wm_concat(distinct name) as names from demotable group by group_id
0
marko

unten ist undokumentiert und wird von Oracle nicht empfohlen. und kann nicht in Funktion angewendet werden, Fehler anzeigen

select wm_concat(distinct name) as names from demotable group by group_id

grüße zia

0
zia

Ich brauchte diesen Code als Unterabfrage mit einigen Datenfiltern vor der Aggregation auf der Grundlage der äußersten Abfrage. Dies konnte ich jedoch nicht mit dem ausgewählten Antwortcode tun, da dieser Filter in die innerste Auswahl (dritte Abfrage) gehen sollte. und die Filterparameter befanden sich in der äußersten Auswahl (Abfrage der ersten Ebene), was zu dem Fehler ORA-00904 führte: "TB_OUTERMOST". "COL": ungültiger Bezeichner, da der ANSI-SQL-Server diese Tabellenreferenzen (Korrelationsnamen) angibt ) sind nur eine Ebene tief. 

Ich brauchte eine Lösung ohne Ebenen der Unterabfrage, und diese hier war für mich großartig:

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
Felypp Oliveira