多列,多表列到行 unpivot
Posted
技术标签:
【中文标题】多列,多表列到行 unpivot【英文标题】:Multiple columns, multiple table columns to rows unpivot 【发布时间】:2017-01-21 06:09:52 【问题描述】:这是我正在使用的表的 ddl。
CREATE TABLE "BISAMPLE"."SUMLEDGER"
( "FUND" VARCHAR2(6 BYTE),
"ORG" VARCHAR2(6 BYTE),
"ACCT" VARCHAR2(6 BYTE),
"PROG" VARCHAR2(6 BYTE),
"YEAR" NUMBER,
"S01_BUDGET" NUMBER,
"S01_BUDGET_ADJ" NUMBER,
"S01_YTD_ACTV" NUMBER,
"S01_ENCUMB" NUMBER,
"S02_BUDGET" NUMBER,
"S02_BUDGET_ADJ" NUMBER,
"S02_YTD_ACTV" NUMBER,
"S02_ENCUMB" NUMBER
)
这里是示例数据的插入。
REM INSERTING into SUMLEDGER
SET DEFINE OFF;
Insert into SUMLEDGER (FUND,ORG,ACCT,PROG,YEAR,S01_BUDGET,S01_BUDGET_ADJ,S01_YTD_ACTV,S01_ENCUMB,S02_BUDGET,S02_BUDGET_ADJ,S02_YTD_ACTV,S02_ENCUMB) values ('100001','3999','3220','06',6,20,30,15,15,10,20,10,40);
Insert into SUMLEDGER (FUND,ORG,ACCT,PROG,YEAR,S01_BUDGET,S01_BUDGET_ADJ,S01_YTD_ACTV,S01_ENCUMB,S02_BUDGET,S02_BUDGET_ADJ,S02_YTD_ACTV,S02_ENCUMB) values ('100001','3999','3220','06',7,20,30,15,15,10,20,30,40);
Insert into SUMLEDGER (FUND,ORG,ACCT,PROG,YEAR,S01_BUDGET,S01_BUDGET_ADJ,S01_YTD_ACTV,S01_ENCUMB,S02_BUDGET,S02_BUDGET_ADJ,S02_YTD_ACTV,S02_ENCUMB) values ('100001','3999','3460','06',6,25,30,20,20,20,20,30,40);
Insert into SUMLEDGER (FUND,ORG,ACCT,PROG,YEAR,S01_BUDGET,S01_BUDGET_ADJ,S01_YTD_ACTV,S01_ENCUMB,S02_BUDGET,S02_BUDGET_ADJ,S02_YTD_ACTV,S02_ENCUMB) values ('100001','3999','3220','06',8,20,35,25,30,30,22,15,30);
这是将在此查询中使用的第二个表。
CREATE TABLE "BISAMPLE"."FUNDING"
( "FUNDING_START_DATE" DATE,
"FUNDING_NUMBER" VARCHAR2(6 BYTE)
)
这是表格插入。
REM INSERTING into FUNDING
SET DEFINE OFF;
Insert into FUNDING (FUNDING_START_DATE,FUNDING_NUMBER) values (to_date('21-JAN-2017 03:47:42','DD-MON-RRRR HH24:MI:SS'),'100001');
我正在尝试使用 unpivot 函数将我的列转换为行。但我目前非常不成功。但是,我可以使用以下查询来完成相同的输出。
SELECT
FUND,
ORG,
ACCT,
PROG,
YEAR,
SUM(S01_BUDGET + S01_BUDGET_ADJ) BUDG,
S01_YTD_ACTV YEAR_TO_DATE,
S01_ENCUMB ENCUMBRANCE,
'01' AS SPERIOD,
CASE
--PERIOD 01
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JAN'
THEN '01' --JAN PERIOD 01
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'FEB'
THEN '02' --FEB
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAR'
THEN '03' --MAR
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'APR'
THEN '04'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAY'
THEN '05'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUN'
THEN '06'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUL'
THEN '07'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'AUG'
THEN '08' --AUG
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'SEP'
THEN '09'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'OCT'
THEN '10' --OCT
WHEN SUBSTR(TO_CHAR(FUNDING_NUMBER,'MON-YYYY'),1,3) = 'NOV'
THEN '11'
WHEN SUBSTR(TO_CHAR(FUNDING_NUMBER,'MON-YYYY'),1,3) = 'DEC'
THEN '12'
ELSE '00'
END AS SMONTH,
(CASE
--PERIOD 01
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JAN'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'FEB'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAR'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'APR'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAY'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUN'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUL'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'AUG'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'SEP'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'OCT'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'NOV'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'DEC'
THEN TO_NUMBER(YEAR)
ELSE TO_NUMBER(YEAR)
END) AS S_YEAR
FROM SUMLEDGER ,
FUNDING
WHERE FUNDING_NUMBER = FUND
group by
FUND,
ORG,
ACCT,
PROG,
YEAR,
S01_YTD_ACTV ,
S01_ENCUMB,
'01' ,
CASE
--PERIOD 01
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JAN'
THEN '01' --JAN PERIOD 01
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'FEB'
THEN '02' --FEB
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAR'
THEN '03' --MAR
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'APR'
THEN '04'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAY'
THEN '05'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUN'
THEN '06'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUL'
THEN '07'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'AUG'
THEN '08' --AUG
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'SEP'
THEN '09'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'OCT'
THEN '10' --OCT
WHEN SUBSTR(TO_CHAR(FUNDING_NUMBER,'MON-YYYY'),1,3) = 'NOV'
THEN '11'
WHEN SUBSTR(TO_CHAR(FUNDING_NUMBER,'MON-YYYY'),1,3) = 'DEC'
THEN '12'
ELSE '00'
END ,
(CASE
--PERIOD 01
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JAN'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'FEB'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAR'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'APR'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAY'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUN'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUL'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'AUG'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'SEP'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'OCT'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'NOV'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'DEC'
THEN TO_NUMBER(YEAR)
ELSE TO_NUMBER(YEAR)
END)
UNION ALL
SELECT
FUND,
ORG,
ACCT,
PROG,
YEAR,
SUM(S02_BUDGET + S02_BUDGET_ADJ) BUDG,
S02_YTD_ACTV YEAR_TO_DATE,
S02_ENCUMB ENCUMBRANCE,
'01' AS SPERIOD,
CASE
--PERIOD 01
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JAN'
THEN '02' --JAN PERIOD 01
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'FEB'
THEN '03' --FEB
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAR'
THEN '04' --MAR
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'APR'
THEN '05'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAY'
THEN '06'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUN'
THEN '07'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUL'
THEN '08'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'AUG'
THEN '09' --AUG
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'SEP'
THEN '10'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'OCT'
THEN '11' --OCT
WHEN SUBSTR(TO_CHAR(FUNDING_NUMBER,'MON-YYYY'),1,3) = 'NOV'
THEN '12'
WHEN SUBSTR(TO_CHAR(FUNDING_NUMBER,'MON-YYYY'),1,3) = 'DEC'
THEN '01'
ELSE '00'
END AS SMONTH,
(CASE
--PERIOD 02
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JAN'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'FEB'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAR'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'APR'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAY'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUN'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUL'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'AUG'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'SEP'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'OCT'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'NOV'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'DEC'
THEN TO_NUMBER(YEAR)+1
ELSE TO_NUMBER(YEAR)
END) AS S_YEAR
FROM SUMLEDGER ,
FUNDING
WHERE FUNDING_NUMBER = FUND
group by
FUND,
ORG,
ACCT,
PROG,
YEAR,
S02_YTD_ACTV ,
S02_ENCUMB ,
'01' ,
CASE
--PERIOD 01
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JAN'
THEN '02' --JAN PERIOD 01
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'FEB'
THEN '03' --FEB
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAR'
THEN '04' --MAR
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'APR'
THEN '05'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAY'
THEN '06'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUN'
THEN '07'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUL'
THEN '08'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'AUG'
THEN '09' --AUG
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'SEP'
THEN '10'
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'OCT'
THEN '11' --OCT
WHEN SUBSTR(TO_CHAR(FUNDING_NUMBER,'MON-YYYY'),1,3) = 'NOV'
THEN '12'
WHEN SUBSTR(TO_CHAR(FUNDING_NUMBER,'MON-YYYY'),1,3) = 'DEC'
THEN '01'
ELSE '00'
END ,
(CASE
--PERIOD 02
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JAN'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'FEB'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAR'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'APR'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'MAY'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUN'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'JUL'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'AUG'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'SEP'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'OCT'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'NOV'
THEN TO_NUMBER(YEAR)
WHEN SUBSTR(TO_CHAR(FUNDING_START_DATE,'MON-YYYY'),1,3) = 'DEC'
THEN TO_NUMBER(YEAR)+1
ELSE TO_NUMBER(YEAR)
END)
有人可以帮我用 unpivot 函数重写这个吗?使用上述方法将需要我至少合并 14 次,因为有 14 个可能的句点/列快速抬头此表包含大约 98 列我已将此处的示例减少为少数列以便更好地解释而不是压倒。
这是我要复制的输出
"FUND" "ORG" "ACCT" "PROG" "YEAR" "BUDG" "YEAR_TO_DATE" "ENCUMBRANCE" "SPERIOD" "SMONTH" "S_YEAR"
"100001" "3999" "3220" "06" 6 50 15 15 "01" "01" 6
"100001" "3999" "3220" "06" 7 50 15 15 "01" "01" 7
"100001" "3999" "3220" "06" 8 55 25 30 "01" "01" 8
"100001" "3999" "3460" "06" 6 55 20 20 "01" "01" 6
"100001" "3999" "3220" "06" 6 30 10 40 "01" "02" 6
"100001" "3999" "3220" "06" 8 52 15 30 "01" "02" 8
"100001" "3999" "3460" "06" 6 40 30 40 "01" "02" 6
"100001" "3999" "3220" "06" 7 30 30 40 "01" "02" 7
【问题讨论】:
仍然试图了解这里发生了什么(如果我能理解这个问题并且我可以回答它,我会添加一个答案)。不过,快速观察一下,substr(to_char(some_date, 'MON-YYYY'), 1, 3)
可以写成to_char(some_date, 'MON')
更简洁有效; CASE
语句可以写得更紧凑,如下所示:CASE TO_CHAR(some_date, 'MON') WHEN 'JAN' THEN ... WHEN 'FEB' THEN ...
- 这样你就不需要重复表达式 12 次。
【参考方案1】:
您在预期结果中的speriod
不正确。最后四行应该有 02。
试试这个:
select
s.fund,
s.org,
s.acct,
s.prog,
s.year,
s.budget + s.budget_adj budg,
s.year_to_date,
s.encumbrance,
s.s_period,
to_number(to_char(add_months(f.funding_start_date, s_period - 1), 'MM')) s_month,
decode(to_char(f.funding_start_date,'MM'),'12',year + s_period - 1, year) s_year
from (
select *
from sumledger
unpivot (
(budget, budget_adj, year_to_date, encumbrance)
for s_period in (
(s01_budget,s01_budget_adj,s01_ytd_actv,s01_encumb) as 1,
(s02_budget,s02_budget_adj,s02_ytd_actv,s02_encumb) as 2)
)
) s inner join funding f on s.fund = f.funding_number;
生产:
【讨论】:
你是很棒的古夫。谢谢!以上是关于多列,多表列到行 unpivot的主要内容,如果未能解决你的问题,请参考以下文章