oracle-databaseover-clause

limit data within an over statement in oracle


I want to Aggregate a column over timestamps.

Here an example:

Table contains columns like col1, col2, ..., col_ts (timestamp column).

SELECT
SUM(col1) OVER (ORDER BY col_ts ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING) SUM1,
SUM(col2) OVER (ORDER BY col_ts ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING) SUM2
FROM ...

Now i want only the 2 PRECEDING and the 2 FOLLOWING ROWS SUMMED when the difference between the timestamps are <= 5 minutes.

For example, lets look at these timestamp values:

14.09.15 15:44:00
14.09.15 15:50:00
14.09.15 15:51:00
14.09.15 15:52:00
14.09.15 15:53:00

When were are at the row with the timestamp value "14.09.15 15:51:00", i want the SUM OVER the values from 15:50 until 15:53, because the difference between 15:50 and 15:44 is bigger than 5 minutes.

Is there a way to write such a condition in the over clause?

Or is there anyone with a good and performant solution to this?


Solution

  • ok, i see the problem here. thanks florin. so what about some preprocessing? i could find a solution, but i am not sure if there is a faster solution:

    select col_ts, 
           n, 
           SUM(n) OVER (ORDER BY col_ts ROWS BETWEEN LEFT_VALUE PRECEDING AND RIGHT_VALUE FOLLOWING) MY_SUM,
           SUM(n) OVER (ORDER BY col_ts RANGE BETWEEN interval '5' second PRECEDING AND interval '5' second FOLLOWING) OLD_SUM
    from (
           select col_ts,
                  n,
                  CASE
                  WHEN (LEAD(col_ts,1) OVER (ORDER BY col_ts ) - col_ts) <= INTERVAL '5' second 
                  THEN 
                       CASE
                       WHEN (LEAD(col_ts,2) OVER (ORDER BY col_ts ) - LEAD(col_ts,1) OVER (ORDER BY col_ts )) <= INTERVAL '5' second 
                       THEN 2 
                       ELSE 1
                       END
                 ELSE 0
                 END AS RIGHT_VALUE,
                 CASE 
                 WHEN (col_ts - LAG(col_ts,1) OVER (ORDER BY col_ts ) ) <= INTERVAL '5' second 
                 THEN 
                      CASE 
                      WHEN (LAG(col_ts,1) OVER (ORDER BY col_ts ) - LAG(col_ts,2) OVER (ORDER BY col_ts )) <= INTERVAL '5' second 
                      THEN 2 
                      ELSE 1
                      END
                ELSE 0
                END AS LEFT_VALUE
          from fg_test
      );
    

    Result:

    COL_TS                           N   MY_SUM      OLD_SUM
    ---------------------------  -----  -------  -----------
    15.09.15 09:34:24,069000000      1        6            6
    15.09.15 09:34:28,000000000      2       10           15
    15.09.15 09:34:29,000000000      3       15           15
    15.09.15 09:34:30,000000000      4       14           14
    15.09.15 09:34:31,000000000      5       12           14
    15.09.15 09:34:37,000000000      6        6            6
    

    what do you think?