Simple SQL Solution
WITH YOURTABLE AS
(
SELECT 'a' AS PARENT,'b' AS CHILD,'JAN' AS MONTH,2 AS QUANTITY FROM DUAL
UNION ALL
SELECT 'a','b','FEB',3 FROM DUAL
UNION ALL
SELECT 'a','b','MAR',1 FROM DUAL
UNION ALL
SELECT 'a','c','JAN',5 FROM DUAL
UNION ALL
SELECT 'a','c','FEB',6 FROM DUAL
UNION ALL
SELECT 'a','c','MAR',3 FROM DUAL
)
SELECT
PARENT,
CHILD,
MAX(DECODE( MONTH,'JAN',QUANTITY,0)) AS JAN,
MAX(DECODE( MONTH,'FEB',QUANTITY,0)) AS FEB,
MAX(DECODE( MONTH,'MAR',QUANTITY,0)) AS MAR,
MAX(DECODE( MONTH,'APR',QUANTITY,0)) AS APR,
MAX(DECODE( MONTH,'MAY',QUANTITY,0)) AS MAY,
MAX(DECODE( MONTH,'JUN',QUANTITY,0)) AS JUN,
MAX(DECODE( MONTH,'JUL',QUANTITY,0)) AS JUL,
MAX(DECODE( MONTH,'AUG',QUANTITY,0)) AS AUG,
MAX(DECODE( MONTH,'SEP',QUANTITY,0)) AS SEP,
MAX(DECODE( MONTH,'OCT',QUANTITY,0)) AS OCT,
MAX(DECODE( MONTH,'NOV',QUANTITY,0)) AS NOV,
MAX(DECODE( MONTH,'DEC',QUANTITY,0)) AS DEC
FROM
YOURTABLE
GROUP BY PARENT,CHILD
DEMO: SQL Fiddle
Bit Complex PL/SQL Solution:
The result has to be ordered by PARENT,CHILD
DECLARE
CURSOR MYCUR
IS
SELECT 'a' AS PARENT,'b' AS CHILD,'JAN' AS MONTH,2 AS QUANTITY FROM DUAL
UNION ALL
SELECT 'a','b','FEB',3 FROM DUAL
UNION ALL
SELECT 'a','b','MAR',1 FROM DUAL
UNION ALL
SELECT 'a','c','JAN',5 FROM DUAL
UNION ALL
SELECT 'a','c','FEB',6 FROM DUAL
UNION ALL
SELECT 'a','c','MAR',3 FROM DUAL;
v_MYTYPE MYCUR%ROWTYPE;
v_prev_child VARCHAR2(100);
ROWSTR VARCHAR2(4000);
TYPE MONTHS IS TABLE OF VARCHAR2(10) INDEX BY VARCHAR2(30);
v_MONTHS MONTHS;
BEGIN
/* Create a associative array of months initialised with quantiy 0 */
FOR REC IN (SELECT TO_CHAR(ADD_MONTHS(TRUNC(sysdate,'YYYY'),level-1),'MON') AS MONTH_NAME
FROM DUAL
CONNECT BY LEVEL <= 12)
LOOP
v_MONTHS(REC.MONTH_NAME) := 0;
END LOOP;
FOR REC IN MYCUR
LOOP
IF(v_prev_child IS NULL) THEN
v_prev_child := REC.CHILD;
ROWSTR := REC.PARENT||' '||REC.CHILD;
v_MONTHS(REC.MONTH) := REC.QUANTITY;
ELSIF(v_prev_child = REC.CHILD) THEN
v_MONTHS(REC.MONTH) := REC.QUANTITY;
ELSE
FOR REC IN (SELECT TO_CHAR(ADD_MONTHS(TRUNC(sysdate,'YYYY'),level-1),'MON') AS MONTH_NAME
FROM DUAL
CONNECT BY LEVEL <= 12)
LOOP
ROWSTR := ROWSTR||' '||v_MONTHS(REC.MONTH_NAME);
v_MONTHS(REC.MONTH_NAME) := 0; /* Initialse to 0 again*/
END LOOP;
DBMS_OUTPUT.PUT_LINE(ROWSTR);
v_prev_child := REC.CHILD;
ROWSTR := REC.PARENT||' '||REC.CHILD;
v_MONTHS(REC.MONTH) := REC.QUANTITY;
END IF;
END LOOP;
FOR REC IN (SELECT TO_CHAR(ADD_MONTHS(TRUNC(sysdate,'YYYY'),level-1),'MON') AS MONTH_NAME
FROM DUAL
CONNECT BY LEVEL <= 12)
LOOP
ROWSTR := ROWSTR||' '||v_MONTHS(REC.MONTH_NAME);
v_MONTHS(REC.MONTH_NAME) := 0; /* Initialse to 0 again*/
END LOOP;
/* Last Row */
DBMS_OUTPUT.PUT_LINE(ROWSTR);
END;
/