在同一个位置转置多个列

时间:2016-05-17 13:13:56

标签: sql oracle pivot decode transpose

我有这个:

Year   Apple   Orange 
1       100       150
2       200       250
3       300       350
2       200       250
1       100       150

我需要这个:

Fruit       1           2            3
Apple      200         400          300
Orange     300         500          350

我有选项A和选项B,但它只转换1个水果,除非我做“全部联盟”。

选项A:

select 
     'Apple' as Fruit
     ,MAX(DECODE(year, '1', sum(Apple)) "1"
     ,MAX(DECODE(year, '2', sum(Apple)) "2"
from MyTable

选项B:

select 
     * 
from (
     select 
          Apple
          ,Year 
     from MyTable
     ) 
PIVOT(sum(Apple) for year in ('1', '2', '3'))

问题:

U可以在没有“联盟”的情况下转置所有列吗?

2 个答案:

答案 0 :(得分:4)

Oracle安装程序

CREATE TABLE table_name ( year, apple, orange ) AS
SELECT 1, 100, 150 FROM DUAL UNION ALL
SELECT 2, 200, 250 FROM DUAL UNION ALL
SELECT 3, 300, 350 FROM DUAL UNION ALL
SELECT 2, 200, 250 FROM DUAL UNION ALL
SELECT 1, 100, 150 FROM DUAL;

查询 - 取消透视然后转动

SELECT *
FROM   (
  SELECT *
  FROM   table_name
  UNPIVOT( value FOR fruit IN ( Apple, Orange ) )
)
PIVOT ( SUM( value ) FOR year IN ( 1, 2, 3 ) );

<强>输出

FRUIT  1   2   3
------ --- --- ---
ORANGE 300 500 350
APPLE  200 400 300

答案 1 :(得分:1)

这是你可以动态完成的。

创建陈述

CREATE TABLE MyTable
    (Year int, Apple int, Orange int) ;
INSERT ALL 
    INTO MyTable (Year, Apple, Orange)      VALUES (1, 100, 150)
    INTO MyTable (Year, Apple, Orange)       VALUES (2, 200, 250)
    INTO MyTable (Year, Apple, Orange)       VALUES (3, 300, 350)
    INTO MyTable (Year, Apple, Orange)       VALUES (2, 200, 250)
    INTO MyTable (Year, Apple, Orange)       VALUES (1, 100, 150)
SELECT * FROM dual;

在SQL Developer或SQLPlus中运行(我在SQL Developer中试过)。 或者您可以将其封装在过程中并返回结果。

SET ServerOutput ON size 100000;
variable rc refcursor;
DECLARE 
v_column_list varchar2 (2000);
v_years varchar2(2000);
BEGIN
    SELECT listagg('"' || column_name || '"', ',') within
    GROUP (ORDER BY column_id)
    INTO v_column_list
    FROM all_tab_columns
    WHERE table_name = 'MYTABLE'
        AND column_name <> 'YEAR';

    SELECT listagg(year, ',') within
    GROUP (ORDER BY year)
    INTO v_years
    FROM (
        SELECT DISTINCT year
        FROM MyTable);
--  dbms_output.put_line(' v_column_list =' || v_column_list);
--  dbms_output.put_line(' v_years =' || v_years);
    OPEN :rc FOR 
    'SELECT * FROM 
   ( SELECT *
        FROM MyTable 
          UNPIVOT ( val for fruit in ( ' || v_column_list || ' ) 
                  )
    ) 
    PIVOT ( sum ( val ) for year in ( ' || v_years || ' ) )';
END;
/

PRINT :rc

输出:

------------------------------------------------------------------------
FRUIT   1                       2                       3                      
------  ---------------------- ---------------------- ---------------------- 
ORANGE  300                     500                     350                 
APPLE   200                     400                     300