Heldigvis fungerer det med listagg( ... )
funktion leveret siden 11.2
(vi kører allerede), så vi behøvede ikke undersøge nærmere:
listagg( abc, ',' ) within group ( order by abc )
(Hvor wm_concat(...)
er, som man burde vide, en intern og officielt ikke-understøttet funktion.)
en temmelig god løsning
(fordi den ikke er så oppustet) for at implementere den distinkte
funktionalitet er via selvrefererende regexp-funktionalitet hvilket burde virke i mange tilfælde:
regexp_replace(
listagg( abc, ',' ) within group ( order by abc )
, '(^|,)(.+)(,\2)+', '\1\2' )
(Måske/forhåbentlig vil vi se nogle fungerende listagg( distinct abc )
funktionalitet i fremtiden, som ville være meget pæn og cool ligesom wm_concat
syntaks. For eksempel. dette er ikke noget problem siden lang tid med Postgres' string_agg( distinct abc )
)
-- 1: postgres sql example:
select string_agg( distinct x, ',' ) from unnest('{a,b,a}'::text[]) as x`
Hvis listen overstiger 4000 tegn , man kan ikke bruge listagg
længere (ORA-22922
igen). Men heldigvis kan vi bruge xmlagg
funktion her (som nævnt her
).Hvis du ønsker at realisere en særlig på et 4000-tegn-trunkeret resultat
her kan du udkommentere (1)
-markerede linjer .
-- in smallercase everything that could/should be special for your query
-- comment in (1) to realize a distinct on a 4000 chars truncated result
WITH cfg AS (
SELECT
',' AS list_delim,
'([^,]+)(,\1)*(,|$)' AS list_dist_match, -- regexp match for distinct functionality
'\1\3' AS LIST_DIST_REPL -- regexp replace for distinct functionality
FROM DUAL
)
SELECT
--REGEXP_REPLACE( DBMS_LOB.SUBSTR( -- (1)
RTRIM( XMLAGG( XMLELEMENT( E, mycol, listdelim ).EXTRACT('//text()')
ORDER BY mycol ).GetClobVal(), LIST_DELIM )
--, 4000 ), LIST_DIST_MATCH, LIST_DIST_REPL ) -- (1)
AS mylist
FROM mytab, CFG