Running total over repeating group by items based on time in Oracle SQL

百般思念 提交于 2019-12-02 10:31:19

In order to get the sums you are looking for you need a way to group the values you are interested in. You can generate a grouping ID by using the a couple of ROW_NUMBER analytic functions, one partitioned by the key value. However due to your need to duplicate the KEY column values this will need to be done in a couple of stages:

WITH t1 AS (
  SELECT dta.*
       , last_value(KEY IGNORE NULLS)          -- Fill in the missing
               OVER (ORDER BY TIME ASC) key2   -- key values
    FROM your_data dta
), t2 AS (
  SELECT t1.*
       , row_number() OVER (ORDER BY TIME)     -- Generate a
       - row_number() OVER (PARTITION BY key2  -- grouping ID
                                ORDER BY TIME) gp
    FROM t1
)
SELECT t2.*
     , sum(amt) OVER (PARTITION BY gp, key2
                          ORDER BY TIME) running_sums
  FROM t2;

The above query creates a running sum of AMT that restarts every time the key value changes. Whereas the following query used in place of the last select statement above gives the requested results, which I wouldn't term a running sum.

SELECT key2
     , MIN(TIME) start_time
     , MAX(TIME) stop_time
     , sum(amt) amt
  FROM t2
 GROUP BY key2, gp;

To see the full time values you may want to either alter your session NLS_DATE_FORMAT as below:

ALTER SESSION SET NLS_DATE_FORMAT='DD-MM-RRRR HH24:MI:SS';

Or wrap each date column in a TO_CHAR function for output purposes.

I'm not sure what your example data has to do with the queries (your sample data is one table, for instance and the sample queries have many queries). But, for assigning the keys, you can use LAG() with the IGNORE NULLS option:

select s.*,
       lag(key ignore nulls) over (order by start) as new_key
from sample s;

Then, you want to group groups of the same key together. One method is a difference of row numbers. The final step is aggregation:

select new_key, min(time), max(time), sum(amount)
from (select s.*,
             (row_number() over (order by start) -
              row_number() over (partition by new_key order by start)
             ) as grp
      from (select s.*,
                   lag(key ignore nulls) over (order by start) as new_key
            from sample s
           ) s
     ) s
group by new_key, grp;

Assigning a group number whenever Key is not NULL can easily be calculated together with the LAG:

LAG(key ignore NULLS) OVER (ORDER BY time) AS new_key,
COUNT(key) OVER (ORDER BY time ROWS UNBOUNDED PRECEDING) AS grp
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!