The main function is STRING_AGG, which you can use the same way as other aggregate functions. Example:
select employee_id, string_agg( job_id ) job_list from job_history group by employee_id;Here's the output in SQL Plus:
EMPLOYEE_ID JOB_LIST ----------- ---------------------------------------- 101 AC_ACCOUNT,AC_MGR 102 IT_PROG 114 ST_CLERK 122 ST_CLERK 176 SA_REP,SA_MAN 200 AD_ASST,AC_ACCOUNT 201 MK_REP 7 rows selected.The delimiter by default is comma (,), and is controlled by a store package STRING_AGG_CONTROL. To change it, you can use:
begin string_agg_control.g_delim := '|'; end; /Then run the sql again:
select employee_id, string_agg( job_id ) job_list from job_history group by employee_id; EMPLOYEE_ID JOB_LIST ----------- ---------------------------------------- 101 AC_ACCOUNT|AC_MGR 102 IT_PROG 114 ST_CLERK 122 ST_CLERK 176 SA_REP|SA_MAN 200 AD_ASST|AC_ACCOUNT 201 MK_REP 7 rows selected.The function is implemented using an Oracle user defined type with the help of User-Defined Aggregates Interface. You can find more information in this doc.
Sounds perfect? Not that much -- you cannot order the strings. That means the source strings appear in the aggregate string randomly.
The script is attached:
create or replace package string_agg_control IS g_delim varchar2(100) := ','; end; / CREATE OR REPLACE TYPE t_string_agg AS OBJECT ( g_string VARCHAR2(32767), g_delim VARCHAR2(100), -- Delimiter to seperate the strings STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT t_string_agg) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateIterate(self IN OUT t_string_agg, value IN VARCHAR2 ) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateTerminate(self IN t_string_agg, returnValue OUT VARCHAR2, flags IN NUMBER) RETURN NUMBER, MEMBER FUNCTION ODCIAggregateMerge(self IN OUT t_string_agg, ctx2 IN t_string_agg) RETURN NUMBER ); / SHOW ERRORS CREATE OR REPLACE TYPE BODY t_string_agg IS STATIC FUNCTION ODCIAggregateInitialize(sctx IN OUT t_string_agg) RETURN NUMBER IS BEGIN sctx := t_string_agg( NULL, string_agg_control.g_delim ); RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateIterate(self IN OUT t_string_agg, value IN VARCHAR2 ) RETURN NUMBER IS BEGIN SELF.g_string := self.g_string || self.g_delim || value; RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateTerminate(self IN t_string_agg, returnValue OUT VARCHAR2, flags IN NUMBER) RETURN NUMBER IS BEGIN returnValue := RTRIM(LTRIM(SELF.g_string, self.g_delim ), self.g_delim ); RETURN ODCIConst.Success; END; MEMBER FUNCTION ODCIAggregateMerge(self IN OUT t_string_agg, ctx2 IN t_string_agg) RETURN NUMBER IS BEGIN SELF.g_string := SELF.g_string || self.g_delim || ctx2.g_string; RETURN ODCIConst.Success; END; END; / SHOW ERRORS CREATE OR REPLACE FUNCTION string_agg (p_input VARCHAR2) RETURN VARCHAR2 PARALLEL_ENABLE AGGREGATE USING t_string_agg; / SHOW ERRORS
2 comments:
BTW this is a cracking bit of work that has proved extremely useful. Many thanks. Simon
Thanκs for a marvelοus posting! Ι gеnuinely enϳoyed геаԁing it,
you're a great author.I will be sure to bookmark your blog and definitely will come back very soon. I want to encourage you continue your great job, have a nice holiday weekend!
my website - utah boat rental
Post a Comment