0

甲骨文 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
;

提前致谢!

4

2 回答 2

3

最简单的方法是使用UNPIVOT运算符,自 Oracle 11.1 起可用。

我在输出中包含了数量为 NULL 的月份(如果不需要它们,很容易修改)。我还为每个月创建了两列——一列用于月份名称,另一列用于月份在一年中的位置。名称可以在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
于 2020-06-16T01:19:08.197 回答
1

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

SELECT ORDER_ID, ORDER_YEAR,
       DECODE(LVL,1,'January',2,'February', ...., 12,'December') AS ORDER_MONTH,
       DECODE(LVL,1,QTY_JAN,2,QTY_FEB, ...., 12,QTY_DEC) AS QTY
  FROM YOUR_TABLE
  CROSS JOIN (SELECT LEVEL AS LVL FROM DUAL CONNECT BY LEVEL <= 12);
于 2020-06-16T04:45:36.507 回答