Oracle SQL查询用累积值执行操作

时间:2015-03-03 22:04:44

标签: sql oracle

从服务订单表(SOS),我想以累积的方式生成每月开/关订单率(%)的报告。 SOS表如下所示:

SO      OPEN_DATE      CLOSE_DATE
===================================
01    01-JAN-2014      03-FEB-2014
02    10-JAN-2014      15-JAN-2014
03    03-FEB-2014      10-MAR-2014
04    05-FEB-2014      13-MAR-2014
05    20-FEB-2014      04-APR-2014
06    01-MAR-2014      15-MAR-2014

所需的输出报告(累计费率)应如下所示:

MONTH       A_OPEN  A_CLOSE  RATE
==================================
JAN-2014    2       1         50%
FEB-2014    5       2         40%
MAR-2014    6       5         83%
APR-2014    6       6        100%

要获取累计打开列,我可以执行以下查询:

select
to_char("OPEN_DATE", 'MON-RRRR') MONTH, 
count(*) OPEN,
sum(count(*)) over (order by to_char("OPEN_DATE", 'MON-RRRR')) "ACCUM_OPEN"
from "SOS"
group by to_char("OPEN_DATE", 'MON-RRRR')
order by to_char("OPEN_DATE", 'MON-RRRR')

产生以下输出:

MONTH       OPEN    ACCUM_OPEN
==============================
JAN-2014    2       2
FEB-2014    3       5
MAR-2014    1       6
APR-2014    0       6

要获得累计封闭列,我可以执行以下查询:

select
to_char("CLOSE_DATE", 'MON-RRRR') MONTH, 
count(*) CLOSED,
sum(count(*)) over (order by to_char("CLOSE_DATE", 'MON-RRRR')) "ACCUM_CLOSED"
from "SOS"
group by to_char("CLOSE_DATE", 'MON-RRRR')
order by to_char("CLOSE_DATE", 'MON-RRRR')

产生以下输出:

MONTH       CLOSED  ACCUM_CLOSED
================================
JAN-2014    1       1
FEB-2014    1       2
MAR-2014    3       5
APR-2014    1       6

我在同时管理两个不同列中的OVER查询时遇到了麻烦。

有什么想法吗?谢谢!

1 个答案:

答案 0 :(得分:0)

由于您已经知道如何生成两个回答问题部分的行集,您可以简单地加入它们:

WITH open_by_month AS (
  ...your first query here...
)
, closed_by_month AS (
  ...your second query here...
)
SELECT *
  FROM open_by_month
  FULL OUTER JOIN closed_by_month USING (month)
ORDER BY month

完整的外部联接将生成几个月没有打开或没有关闭的行。但是,我认为这些行将缺少累计总数。

更完整的解决方案是生成您感兴趣的所有月份的列表;得到每个月新开启和关闭的数量;然后做积累。希望这能告诉你这个想法 - 我现在不能花时间测试语法和边缘条件。

WITH months AS (
  SELECT add_months( first_open, level - 1 ) month
    FROM (SELECT first_day(min(open_date)) FROM sos) first_open
    CONNECT BY level <= months_between( sysdate, first_open )
)
, opens AS (
  SELECT month, count(*) open_count FROM months LEFT JOIN sos
    ON open_date BETWEEN month AND last_day(month)
    GROUP BY month
)
, closes AS (
  SELECT month, count(*) close_count FROM months LEFT JOIN sos
    ON close_date BETWEEN month AND last_day(month)
    GROUP BY month
)
SELECT month, open_cout, close_count,
   SUM(open_count) OVER (ORDER BY month),
   SUM(close_count) OVER (ORDER BY month)
FROM
  opens JOIN closes USING (month)

(我假设这些日期没有时间组件,所以使用LAST_DAY(月)作为上限工作。)