1

I am using the collect function to concatenate strings for a sql query.

    select id,
    tab_to_string(CAST(COLLECT(a.level||' '||d.Number||':  
    '||to_char(nvl(de.eventDate,SYSDATE - 365 * 100))) AS t_varchar2_tab)) AS MyVar
    from Mytable
    groupby id

The output of this query is like:

    Id    Myvar
    1     level : 27-Jan-09,level : 27-Mar-08, level : 2-Apr-10
    2     level : 7-Jun-06,level : 27-Dec-08, level : 2-Nov-08
    3     level : 27-July-10,level : 27-Mar-06, level : 2-Apr-10

But i want the "Myvar" value to be ordered by the date field within the concatenated string

so for the Id = 1, the output should be like

    level : 27-Mar-08, level : 27-Jan-09, level : 2-Apr-10

Below is the code for tab_to_string function

source: http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php#wm_concat

    CREATE OR REPLACE FUNCTION tab_to_string (p_varchar2_tab  IN  t_varchar2_tab,
                                      p_delimiter     IN  VARCHAR2 DEFAULT ',') 
    RETURN VARCHAR2 IS
    l_string     VARCHAR2(32767);
    BEGIN
    FOR i IN p_varchar2_tab.FIRST .. p_varchar2_tab.LAST LOOP
    IF i != p_varchar2_tab.FIRST THEN
    l_string := l_string || p_delimiter;
    END IF;
    l_string := l_string || p_varchar2_tab(i);
    END LOOP;
    RETURN l_string;
    END tab_to_string;

I am using Oracle 10g.

Thanks Prash

1 Answer 1

2

to get an ordered list, there's a few ways. the simplest is :

select id, str
  from (select id, 
               wm_concat('level : ' || to_char(nvl(eventDate,SYSDATE - 365 * 100))) 
                 over (partition by id order by eventdate) str,
               row_number() over (partition by id order by eventdate desc) rn
         from Mytable)
 where rn = 1;

or if you're using the "stragg" user defined aggregate:

  select id, str
  from (select id, 
               string_agg('level : ' || to_char(nvl(eventDate,SYSDATE - 365 * 100))) 
                 over (partition by id order by eventdate) str,
               row_number() over (partition by id order by eventdate desc) rn
         from Mytable)
 where rn = 1;

eg

SQL> select id, str
  2    from (select id,
  3                 string_agg('level : ' || to_char(nvl(eventDate,SYSDATE - 365 * 100)))
  4                   over (partition by id order by eventdate) str,
  5                 row_number() over (partition by id order by eventdate desc) rn
  6           from Mytable)
  7   where rn = 1;

        ID STR
---------- ----------------------------------------------------------------------
         1 level : 27-MAR-08,level : 27-JAN-09,level : 02-APR-10
         2 level : 07-JUN-06,level : 02-NOV-08,level : 27-DEC-08
         3 level : 27-MAR-06,level : 02-APR-10,level : 27-JUL-10
Sign up to request clarification or add additional context in comments.

1 Comment

Another option is to use collect(... order by de.eventDate). That syntax is documented in 11g, and not 10g, but still works in 10g.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.