将多列放入行中

问题描述 投票:0回答:2

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
;

提前感谢!

oracle plsql oracle12c oracle19c
2个回答
0
投票

最简单的方法是使用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

0
投票

您可以按如下方式使用层次结构查询:

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;
© www.soinside.com 2019 - 2024. All rights reserved.