'SQL-how can i product/ multiply across partitions with window functions

The input I have is composed of the following columns: time, UseID, and value. I want to get the plt column as the product of successive numbers.

I know about the existence of the SUM window function to apply sum over rows, but how to handle the product?

time UseID value plt
t1 116C123 a a
t2 116C123 b a*b
t3 116C123 c a*b*c
t4 116C123 d a*b*c*d
t2 116C111 a1 a1
t3 116C111 b1 a1*b1
t4 116C111 c1 a1*b1*c1

Note: the output should be in the domain of real numbers.



Solution 1:[1]

You can use logarithms for this!

log(x) + log(y) = log(x*y) ==> x*y = exp(log(x) + log(y))

so your query becomes:

select
    time,
    UseID,
    value,
    exp(
        sum(ln(value)) over (
            partition by UseID
            order by time asc
            rows between unbounded preceding and current row
        )
    ) as plt
from your_table

Solution 2:[2]

Attention: This solution will work on a Postgres DB, not on a Redshift DB. I created this because first Postgres was tagged in the question as DB type. If I should remove the answer, please let me know.

Assuming the last line of your sample data is incorrect (should be useid 116C111 instead of 116C123), you could do something like this to do a multiplication:

CREATE AGGREGATE MULTIPLICATE(int8) (SFUNC = int8mul, STYPE = int8);

and then use this in your query:

SELECT
time,
useid,
value,
MULTIPLICATE(value) OVER (PARTITION BY useid ORDER BY useid, value) AS plt
FROM input 
GROUP BY useid, value, time
ORDER BY useid, value, time;

Please see the working example here: db<>fiddle

If your sample data really is correct, you should please describe the logic behind it.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 tconbeer
Solution 2