Luckily, it works with the listagg( ... )
function provided since 11.2
(we are already running on), so we did not have to investigate further:
listagg( abc, ',' ) within group ( order by abc )
(Where wm_concat(...)
is, as one should know, some internal and officially unsupported function.)
a rather nice solution (because it is not so bloated) to implement the distinct
functionality is via self-referencing regexp functionality which should work in many cases:
regexp_replace(
listagg( abc, ',' ) within group ( order by abc )
, '(^|,)(.+)(,2)+', '12' )
(Maybe/Hopefully we will see some working listagg( distinct abc )
functionality in the future, which would be very neat and cool like the wm_concat
syntax. E.g. this is no problem since a long time with Postgres' string_agg( distinct abc )
1 )
-- 1: postgres sql example:
select string_agg( distinct x, ',' ) from unnest('{a,b,a}'::text[]) as x`
If the list exceeds 4000 characters, one cannot use listagg
anymore (ORA-22922
again).
But luckily we can use the xmlagg
function here (as mentioned here).
If you want to realize a distinct
on a 4000-chars-truncated result here, you could outcomment the (1)
-marked lines.
-- 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
'13' 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