Question

I have a list of values in a column 1, now I want to get the sum of next 5 row values or 6 row values like below and populate the value in appropriate column.

enter image description here

for example if you see 1st row value of the column 'next-5row-value' would be the sum of values from the current row to the next 5 rows which would be 9 and the next column would be sum of next 5 row values from that reference point.

I am trying to write functions to loop through to arrive at the sum. Is there an efficient way . can some one help me out. I am using postgres, greenplum . Thanks!

Was it helpful?

Solution

for example if you have this simple table:

sebpa=# \d numbers
                         Table "public.numbers"
 Column |  Type   |                      Modifiers
--------+---------+------------------------------------------------------
 id     | integer | not null default nextval('numbers_id_seq'::regclass)
 i      | integer |

sebpa=# select * from numbers limit 15;
  id  | i
------+---
 3001 | 3
 3002 | 0
 3003 | 5
 3004 | 1
 3005 | 1
 3006 | 4
 3007 | 1
 3008 | 1
 3009 | 4
 3010 | 0
 3011 | 4
 3012 | 0
 3013 | 3
 3014 | 2
 3015 | 1
(15 rows)

you can use this sql:

sebpa=# select id, i, sum(i) over( order by id rows between 0 preceding and 4 following) from numbers;
  id  | i | sum
------+---+-----
 3001 | 3 |  10
 3002 | 0 |  11
 3003 | 5 |  12
 3004 | 1 |   8
 3005 | 1 |  11
 3006 | 4 |  10
 3007 | 1 |  10
 3008 | 1 |   9
 3009 | 4 |  11
 3010 | 0 |   9
 3011 | 4 |  10
 3012 | 0 |  10
 3013 | 3 |  13
 3014 | 2 |  15
 3015 | 1 |  17
 3016 | 4 |  20
 3017 | 3 |  17
--cutted output

OTHER TIPS

You can try something like this:

SELECT V,
       SUM(V) OVER(ORDER BY YourOrderingField
                       ROWS BETWEEN 1 FOLLOWING AND 5 FOLLOWING) AS next_5row_value,
       SUM(V) OVER(ORDER BY YourOrderingField
                       ROWS BETWEEN 1 FOLLOWING AND 6 FOLLOWING) AS next_6row_value
FROM YourTable;

If you don't want NULLs in your "next_5row_value" column (the same for the 6row), you can use the COALESCE function (supported in PostgreSQL too) that returns the first not null expression. Something like this:

SELECT V,
       COALESCE(SUM(V) OVER(ORDER BY YourOrderingField
                            ROWS BETWEEN 1 FOLLOWING AND 5 FOLLOWING), 0) AS next_5row_value,
       COALESCE(SUM(V) OVER(ORDER BY YourOrderingField
                            ROWS BETWEEN 1 FOLLOWING AND 6 FOLLOWING), 0) AS next_6row_value
FROM YourTable;

I don't think Postgres 8.4 supports the full functionality of window frames. You can do this by using lead():

select value,
       (value +
        lead(value, 1) over (order by id) +
        lead(value, 2) over (order by id) +
        lead(value, 3) over (order by id) +
        lead(value, 4) over (order by id)
       ) as next5,
       (value +
        lead(value, 1) over (order by id) +
        lead(value, 2) over (order by id) +
        lead(value, 3) over (order by id) +
        lead(value, 4) over (order by id) +
        lead(value, 5) over (order by id)
       ) as next5
from table t;

Using a window frame definition is definitely a better approach if the database supports it. But the above will also work.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top