Lyckligtvis fungerar det med listagg( ... )
funktion tillhandahållen sedan 11.2
(vi kör redan på), så vi behövde inte undersöka ytterligare:
listagg( abc, ',' ) within group ( order by abc )
(Där wm_concat(...)
är, som man borde veta, någon intern och officiellt ostödd funktion.)
en ganska trevlig lösning
(eftersom den inte är så uppsvälld) för att implementera distinct
funktionalitet är via självrefererande regexp-funktionalitet vilket borde fungera i många fall:
regexp_replace(
listagg( abc, ',' ) within group ( order by abc )
, '(^|,)(.+)(,\2)+', '\1\2' )
(Kanske/förhoppningsvis kommer vi att se några fungerande listagg( distinct abc )
funktionalitet i framtiden, vilket skulle vara väldigt snyggt och coolt som wm_concat
syntax. T.ex. detta är inga problem sedan länge med Postgres' string_agg( distinct abc )
)
-- 1: postgres sql example:
select string_agg( distinct x, ',' ) from unnest('{a,b,a}'::text[]) as x`
Om listan överstiger 4000 tecken , man kan inte använda listagg
längre (ORA-22922
igen).Men lyckligtvis kan vi använda xmlagg
fungerar här (som nämnts här
). Om du vill förverkliga en distinct
på ett 4000-tecken-trunkerat resultat här kan du utkommentera (1)
-markerade 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