Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

oráculo como pivotar minha tabela


se você não quiser um número dinâmico de colunas, terá que fazer essa abordagem e usar um tipo para manter as colunas (já que o sql estático tem um número fixo de colunas).
SQL> create table my_table (cy_name varchar2(3), ca_date date, ca_value number);

Table created.

SQL> alter session set nls_date_format='mm/dd/yyyy';

Session altered.

SQL> insert into my_table
  2  select 'CUL' cy_name, to_date('1/4/2013') ca_date, 12 ca_value from dual
  3  union all
  4  select 'CUL' cy_name, to_date('12/31/2012') ca_date, 12 ca_value from dual
  5  union all
  6  select 'CUL' cy_name, to_date('1/3/2013') ca_date, 12 ca_value from dual
  7  union all
  8  select 'CUR' cy_name, to_date('1/6/2013') ca_date, 12 ca_value from dual
  9  union all
 10  select 'CUR' cy_name, to_date('12/6/2013') ca_date, 12 ca_value from dual;

5 rows created.

SQL>
SQL> drop type colTab;

Type dropped.

SQL> drop type colType;

Type dropped.

SQL> create type colType as object (colname varchar2(30), value number);
  2  /

Type created.

SQL> create type colTab as table of colType;
  2  /

Type created.

SQL> alter session set nls_date_format='mm/dd/yyyy';

Session altered.

SQL> col val format a80
SQL> set linesize 90
SQL> select cy_name,
  2         cast(multiset(select ca_date, ca_value
  3                         from my_table d
  4                        where d.cy_name = a.cy_name) as coltab) val
  5    from my_table a
  6  group by cy_name;

CY_ VAL(COLNAME, VALUE)
--- --------------------------------------------------------------------------------
CUR COLTAB(COLTYPE('01/06/2013', 12), COLTYPE('12/06/2013', 12))
CUL COLTAB(COLTYPE('01/04/2013', 12), COLTYPE('12/31/2012', 12), COLTYPE('01/03/2013
    ', 12))

ou gere o sql primeiro dinamicamente .. por exemplo:
SQL> select 'select CY_NAME, ' from dual
  2  union all
  3  select case when rownum != 1 then ',' end || str
  4    from (select distinct  'MAX(DECODE(CA_DATE, TO_DATE(''' || to_char(ca_date, 'dd-mm-yyyy') || ''', ''DD-MM-YYYY''), CA_VALUE, NULL)) as "' || to_char(ca_date, 'dd-mm-yyyy
') || '"' str
  5            from my_table a)
  6  union all
  7     select 'FROM MY_TABLE
  8  GROUP BY  CY_NAME; ' from dual
  9  ;

'SELECTCY_NAME,'
------------------------------------------------------------------------------------------
select CY_NAME,
MAX(DECODE(CA_DATE, TO_DATE('04-01-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "04-01-2013"
,MAX(DECODE(CA_DATE, TO_DATE('06-12-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "06-12-2013"
,MAX(DECODE(CA_DATE, TO_DATE('31-12-2012', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "31-12-2012"
,MAX(DECODE(CA_DATE, TO_DATE('03-01-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "03-01-2013"
,MAX(DECODE(CA_DATE, TO_DATE('06-01-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "06-01-2013"
FROM MY_TABLE
GROUP BY  CY_NAME;


7 rows selected.

e execute-o:
SQL> select CY_NAME,
  2  MAX(DECODE(CA_DATE, TO_DATE('04-01-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "04-01-2013"
  3  ,MAX(DECODE(CA_DATE, TO_DATE('06-12-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "06-12-2013"
  4  ,MAX(DECODE(CA_DATE, TO_DATE('31-12-2012', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "31-12-2012"
  5  ,MAX(DECODE(CA_DATE, TO_DATE('03-01-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "03-01-2013"
  6  ,MAX(DECODE(CA_DATE, TO_DATE('06-01-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "06-01-2013"
  7  FROM MY_TABLE
  8  GROUP BY  CY_NAME;

CY_ 04-01-2013 06-12-2013 31-12-2012 03-01-2013 06-01-2013
--- ---------- ---------- ---------- ---------- ----------
CUR                    12                               12
CUL         12                    12         12

ATUALIZE para sua edição:se o número de colunas em sua edição for 7:
SQL> select 'select CY_NAME, ' from dual
  2  union all
  3  select case when rownum != 1 then ',' end || str
  4    from (select 'MAX(DECODE(CA_DATE, TO_DATE('''
  5                 || to_char((d-rownum+1), 'dd-mm-yyyy')
  6                 || ''', ''DD-MM-YYYY''), CA_VALUE, NULL)) as "'
  7                 || to_char((d-rownum+1), 'dd-mm-yyyy') || '"' str
  8            from (select max(ca_date) d from cotton_arv) a
  9          connect by level <= 7 /* change to the number of cols needed */)
 10  union all
 11     select 'FROM V_COTTON_ARV
 12  GROUP BY  CY_NAME; ' from dual
 13  ;

'SELECTCY_NAME,'
------------------------------------------------------------------------------------------------
------------------------
select CY_NAME,
    MAX(DECODE(CA_DATE, TO_DATE('04-01-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "04-01-2013"
    ,MAX(DECODE(CA_DATE, TO_DATE('03-01-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "03-01-2013"
    ,MAX(DECODE(CA_DATE, TO_DATE('02-01-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "02-01-2013"
    ,MAX(DECODE(CA_DATE, TO_DATE('01-01-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "01-01-2013"
    ,MAX(DECODE(CA_DATE, TO_DATE('31-12-2012', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "31-12-2012"
    ,MAX(DECODE(CA_DATE, TO_DATE('30-12-2012', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "30-12-2012"
    ,MAX(DECODE(CA_DATE, TO_DATE('29-12-2012', 'DD-MM-YYYY'), CA_VALUE, NULL)) as "29-12-2012"
    FROM V_COTTON_ARV
    GROUP BY  CY_NAME;