【问题标题】:Oracle SQL query to do operations with accumulated valuesOracle SQL 查询对累积值进行操作
【发布时间】:2015-03-03 22:04:44
【问题描述】:

从服务订单表 (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

所需的输出报告(ACCUMULATED RATE)应如下所示:

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 查询时遇到了麻烦。

有什么想法吗?谢谢!

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

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

    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(month) 作为上限。)

    【讨论】:

    • 谢谢戴夫。我会检查两个想法并尝试。
    猜你喜欢
    • 2020-07-24
    • 2017-09-19
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多