Question

I have data from query in cursor as shown below:

parent   child   month   qty
a          b      jan     2
a          b      feb     3
a          b      mac     1

I want my data to print:

parent child jan feb mac
a        b    2   3   1

How to print this using loop(s)? I have tried using pivot in my query, but the month column is dynamic which i am not able to display it later. Can anyone help?

Was it helpful?

Solution

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;
/

OTHER TIPS

select parent, child, JAN, FEB, MAR, qty
from 
(
select parent, child, month JAN, NULL FEB, NULL MAR, qty
from yourtablename
where month = 'JAN'
and parent = 'a'
and child  = 'b'

UNION ALL

select parent, child, NULL JAN, MONTH FEB, NULL MAR, qty
from yourtablename
where month = 'FEB'
and parent = 'a'
and child  = 'b'


UNION ALL

select parent, child, NULL JAN, NULL FEB, MONTH MAR, qty
from yourtablename
where month = 'MAR'
and parent = 'a'
and child  = 'b'

)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top