同时转置多个列
Transpose multiple Columns at same
我有这个:
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 个水果,除非我做一个 "Union all"。
选项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'))
问题:
你可以转置所有没有 "Union" 的列吗?
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
这是动态执行的方法。
创建报表
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 中试过)。
或者你可以将它封装在一个过程中,并且可以 return 结果。
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
我有这个:
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 个水果,除非我做一个 "Union all"。
选项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'))
问题:
你可以转置所有没有 "Union" 的列吗?
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
这是动态执行的方法。
创建报表
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 中试过)。 或者你可以将它封装在一个过程中,并且可以 return 结果。
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