Showing posts with label TRANSPOSE ROWS TO COLUMNS. Show all posts
Showing posts with label TRANSPOSE ROWS TO COLUMNS. Show all posts

Tuesday, August 25, 2009

TRANSPOSE ROWS TO COLUMNS AND CONVERT TO COMMA SEPRATED VALUES (CSV)

/*Below is the basic sql to transpose rows to columns and concatenate by ','
The key here is using hierarchical queries and oracle supplied sys_connect_by_path function
*/
WITH s1 AS
( SELECT 'A' as col1
FROM dual
UNION
SELECT 'B' as col1
FROM dual
UNION
SELECT 'C' as col1
FROM dual)
SELECT SUBSTR(MAX(sys_connect_by_path(col1,',')),2)
FROM (SELECT col1,
row_number () OVER (ORDER BY col1) as curr,
row_number () OVER (ORDER BY col1)-1 as prev
FROM s1
) vw
CONNECT BY vw.curr = PRIOR prev
SQL> /
SUBSTR(MAX(SYS_CONNECT_BY_PATH(COL1,',')),2)
--------------------------------------------------------------------------------
C,B,A


Here set s1 can be replace with any query data that you want to convert to csv.

To use this as a function/procedure pass the cursor and use its result set as set s1 in the query above. You would need to use a character database type array to collect cursor data

for example:
CREATE OR REPLACE TYPE string_type_array AS TABLE OF VARCHAR2(32767);


CREATE OR REPLACE FUNCTION test_func(p_cur IN OUT sys_refcursor)
RETURN VARCHAR2
AS
l_col_val_tab string_type_array;
l_csv_string VARCHAR2(32767);
BEGIN
LOOP
FETCH p_cur BULK COLLECT INTO l_col_val_tab;
EXIT WHEN p_cur%NOTFOUND;
END LOOP;

WITH s1 AS
(SELECT COLUMN_VALUE as col1
FROM TABLE(l_col_val_tab)
)
SELECT SUBSTR(MAX(sys_connect_by_path(col1,',')),2)
INTO l_csv_string
FROM (SELECT col1,
row_number () OVER (ORDER BY col1) as curr,
row_number () OVER (ORDER BY col1)-1 as prev
FROM s1
) vw
CONNECT BY vw.curr = PRIOR prev;

RETURN l_csv_string;
END test_func;


DECLARE
l_query_cur SYS_REFCURSOR;
BEGIN
OPEN l_query_cur FOR
SELECT 'A' as col1
FROM dual
UNION
SELECT 'B' as col1
FROM dual
UNION
SELECT 'C' as col1
FROM dual;

DBMS_OUTPUT.put_line(test_func(p_cur => l_query_cur));
END;