Na szczęście działa z listagg( ... )
funkcja dostępna od 11.2
(już działamy), więc nie musieliśmy dalej badać:
listagg( abc, ',' ) within group ( order by abc )
(Gdzie wm_concat(...)
jest, jak trzeba wiedzieć, jakąś wewnętrzną i oficjalnie nieobsługiwaną funkcją.)
raczej fajne rozwiązanie
(ponieważ nie jest tak nadęty) zaimplementować distinct
Funkcjonalność jest poprzez samoodwołującą się funkcjonalność wyrażenia regularnego co powinno działać w wielu przypadkach:
regexp_replace(
listagg( abc, ',' ) within group ( order by abc )
, '(^|,)(.+)(,\2)+', '\1\2' )
(Być może/Mam nadzieję, że zobaczymy działający listagg( distinct abc )
funkcjonalność w przyszłości, która byłaby bardzo fajna i fajna jak wm_concat
składnia. Np. nie stanowi to problemu od dawna z string_agg( distinct abc )
Postgresa )
-- 1: postgres sql example:
select string_agg( distinct x, ',' ) from unnest('{a,b,a}'::text[]) as x`
Jeśli lista przekracza 4000 znaków , jeden nie może użyć listagg
już (ORA-22922
ponownie). Ale na szczęście możemy użyć xmlagg
funkcja tutaj (jak wspomniano tutaj
).Jeśli chcesz zrealizować distinct
na wyniku obciętym 4000 znaków tutaj możesz odkomentować (1)
-oznaczone linie .
-- 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