oracle如何转动我的表

时间:2013-01-04 10:33:06

标签: oracle pivot-table

我有这些数据显示在图像中。

enter image description here

我希望像这样显示这些数据

CYNAME    04 JAN 2012   03 JAN 2012 02 JAN 2012 01 JAN-2012
CUL            12           12             12         12

我如何在oracle 10g中实现这一点,以便像这样显示。

更新

My Current Sql Query就像这样

SELECT CY_NAME,
           NVL(MAX(DECODE ( CA_DATE , (SELECT MAX(CA_DATE)   FROM COTTON_ARV), CA_VALUE )),0) "04 JAN 2013",
           NVL(MAX(DECODE ( CA_DATE , (SELECT MAX(CA_DATE)-1 FROM COTTON_ARV), CA_VALUE )),0) "03 JAN 2013",
           NVL(MAX(DECODE ( CA_DATE , (SELECT MAX(CA_DATE)-2 FROM COTTON_ARV), CA_VALUE )),0) "02 JAN 2013",
           NVL(MAX(DECODE ( CA_DATE , (SELECT MAX(CA_DATE)-3 FROM COTTON_ARV), CA_VALUE )),0) "01 JAN 2013",
           NVL(MAX(DECODE ( CA_DATE , (SELECT MAX(CA_DATE)-4 FROM COTTON_ARV), CA_VALUE )),0) "31 DEC 2012",
           NVL(MAX(DECODE ( CA_DATE , (SELECT MAX(CA_DATE)-5 FROM COTTON_ARV), CA_VALUE )),0) "30 DEC 2012",
           NVL(MAX(DECODE ( CA_DATE , (SELECT MAX(CA_DATE)-6 FROM COTTON_ARV), CA_VALUE )),0) "29 DEC 2012"
    FROM      V_COTTON_ARV
    GROUP BY  CY_NAME

问题是alis是固定的但是日期在查询中是动态的。如何根据查询更改别名。或者有没有办法做到这一点

2 个答案:

答案 0 :(得分:2)

如果您不想使用动态数量的列,则必须使用此方法并使用类型来保存列(因为静态sql具有固定数量的列)。

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))

或首先动态生成sql ..eg:

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.

并运行它:

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

更新到您的修改: 如果编辑中的cols数量为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;

答案 1 :(得分:0)

在Oracle 11g之前,您无法使用简单的SQL语句来转动表。

你需要一个PL / SQL程序来构建一个像这样的转向查询:

SELECT CYNAME    
     , 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('02-01-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) AS "02-01-2013"
     , MAX(DECODE(CA_DATE, TO_DATE('03-01-2013', 'DD-MM-YYYY'), CA_VALUE, NULL)) AS "03-01-2013"
     , ...
FROM MY_TABLE
GROUP BY  CYNAME;

如果您只需要运行一次,请手动构建它。