Gelukkig werkt het met de listagg( ... )
functie geleverd sinds 11.2
(we zijn al bezig), dus we hoefden niet verder te onderzoeken:
listagg( abc, ',' ) within group ( order by abc )
(Waar wm_concat(...)
is, zoals men zou moeten weten, een interne en officieel niet-ondersteunde functie.)
een nogal mooie oplossing
(omdat het niet zo opgeblazen is) om de distinct
. te implementeren functionaliteit is via zelfverwijzende regexp-functionaliteit wat in veel gevallen zou moeten werken:
regexp_replace(
listagg( abc, ',' ) within group ( order by abc )
, '(^|,)(.+)(,\2)+', '\1\2' )
(Misschien/hopelijk zullen we enkele werkende listagg( distinct abc )
zien functionaliteit in de toekomst, die heel netjes en cool zou zijn, zoals de wm_concat
syntaxis. bijv. dit is al lang geen probleem met string_agg( distinct abc )
van Postgres )
-- 1: postgres sql example:
select string_agg( distinct x, ',' ) from unnest('{a,b,a}'::text[]) as x`
Als de lijst meer dan 4000 tekens bevat , één kan listagg
niet gebruiken meer (ORA-22922
opnieuw). Maar gelukkig kunnen we de xmlagg
. gebruiken functie hier (zoals hier
).Als u een distinct
wilt realiseren op een resultaat van 4000 tekens afgekapt hier zou je commentaar kunnen geven op de (1)
-gemarkeerde lijnen .
-- 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