Oracle 12c / 19c
我已经继承了以下格式的表中的一些数据(请不要因为某人为什么会以这种格式存储数据而烦恼我-我明白了,但必须使用已有的格式)。业务需要将列的数据转换为行数月(如下所示的目标格式)。
我能够使用下面列出的大并集查询获取我想要的数据,但想看看是否有人有更好/有效的方式来编写它。我也正在考虑创建一份夜间工作,以将该数据转换为新格式(或创建mview)。
来源:
ORDER_ID
ORDER_YEAR
QTY_JAN
QTY_FEB
QTY_MAR
QTY_APR
QTY_MAY
QTY_JUN
QTY_JUL
QTY_AUG
QTY_SEP
QTY_OCT
QTY_NOV
QTY_DEC
目标:
ORDER_ID
ORDER_YEAR
ORDER_MONTH
QTY
查询:
select order_id, order_year, '01' order_month, sum(qty_jan) qty
from order_quantity
group by order_id, order_year
union
select order_id, order_year, '02' order_month, sum(qty_feb) qty
from order_quantity
group by order_id, order_year
union
select order_id, order_year, '03' order_month, sum(qty_mar) qty
from order_quantity
group by order_id, order_year
union
select order_id, order_year, '04' order_month, sum(qty_apr) qty
from order_quantity
group by order_id, order_year
union
select order_id, order_year, '05' order_month, sum(qty_may) qty
from order_quantity
group by order_id, order_year
union
select order_id, order_year, '06' order_month, sum(qty_jun) qty
from order_quantity
group by order_id, order_year
union
select order_id, order_year, '07' order_month, sum(qty_jul) qty
from order_quantity
group by order_id, order_year
union
select order_id, order_year, '08' order_month, sum(qty_aug) qty
from order_quantity
group by order_id, order_year
union
select order_id, order_year, '09' order_month, sum(qty_sep) qty
from order_quantity
group by order_id, order_year
union
select order_id, order_year, '10' order_month, sum(qty_oct) qty
from order_quantity
group by order_id, order_year
union
select order_id, order_year, '11' order_month, sum(qty_nov) qty
from order_quantity
group by order_id, order_year
union
select order_id, order_year, '12' order_month, sum(qty_dec) qty
from order_quantity
group by order_id, order_year
;
提前感谢!
最简单的方法是使用UNPIVOT
运算符,自Oracle 11.1起可用。
我在输出中包括了数量为NULL的月份(如果不需要,可以轻松修改)。我还为每个月创建two列-一个列表示月份名称,另一列表示年份中月份的位置。该名称可以在SELECT
子句中使用(将在输出中显示),而“位置”仅在ORDER BY
子句中使用。
我在WITH
子句中创建了用于测试的示例数据。当然,这不是实际解决方案的一部分。在主查询中使用实际的表名和列名。我只包括前三个月-您应该很容易地将所有12个月都包括在内。
with
order_quantity (order_id, order_year, qty_jan, qty_feb, qty_mar) as (
select 1001, 2018, 300, 450, 200 from dual union all
select 1001, 2019, 400, 250, null from dual union all
select 1001, 2020, 300, null, 200 from dual union all
select 1002, 2019, 540, 230, null from dual union all
select 1002, 2020, null, 300, 800 from dual
)
select order_id, order_year, order_month, qty
from order_quantity
unpivot include nulls (
qty for (order_month, pos) in ( qty_jan as ('January' , 1)
, qty_feb as ('February', 2)
, qty_mar as ('March' , 3)
)
)
order by order_id, order_year, pos
;
输出:
ORDER_ID ORDER_YEAR ORDER_MONTH QTY
---------- ---------- ----------- ----------
1001 2018 January 300
1001 2018 February 450
1001 2018 March 200
1001 2019 January 400
1001 2019 February 250
1001 2019 March
1001 2020 January 300
1001 2020 February
1001 2020 March 200
1002 2019 January 540
1002 2019 February 230
1002 2019 March
1002 2020 January
1002 2020 February 300
1002 2020 March 800
您可以按如下方式使用层次结构查询:
SELECT ORDER_ID, ORDER_YEAR,
DECODE(LEVEL,1,'January',2,'February', ...., 12,'December') AS ORDER_MONTH,
DECODE(LEVEL,1,QTY_JAN,2,QTY_FEB, ...., 12,QTY_DEC) AS QTY
FROM YOUR_TABLE
CONNECT BY LEVEL <= 12;