It's possible to create a rule in preceding rows in sum?

人盡茶涼 提交于 2021-02-13 05:46:45

问题


I have a historical stock variation values and have to calculate the stock value. But I also have a rule that the stock is max(stock, 0), or in other words, if stock is negative, I consider it as zero.

To make this in Big Query, I think the way is like this:

with stock as (
SELECT -7.34 variation, UNION ALL
SELECT -1.81 UNION ALL
SELECT -0.51 UNION ALL
SELECT 17.19 UNION ALL
SELECT -1.63 UNION ALL
SELECT 2.82 UNION ALL
SELECT -1.00 UNION ALL
SELECT 0.56 UNION ALL
SELECT -17.92 UNION ALL
SELECT 0.34 UNION ALL
SELECT 1.02 UNION ALL
SELECT 0.39 UNION ALL
SELECT 0.25 UNION ALL
SELECT 0.65 UNION ALL
SELECT 0.09 UNION ALL
SELECT -0.32 UNION ALL
SELECT -0.40 
)
select variation, sum(variation) over (rows unbounded preceding) as stock from stock

I think the solution is something like saying preceding has to be max(preceding, 0). But I didn't find how to do this.

The results I obtained in query is:

|variation|stock|
|---------|-----|
|-7.34    |-7.34|
|-1.81    |-9.15|
|-0.51    |-9.66|
|17.19    |7.53 |
|-1.63    |5.9  |
|2.82     |8.72 |
|-1.0     |7.72 |
|0.56     |8.28 |
|-17.92   |-9.64|
|0.34     |-9.3 |
|1.02     |-8.28|
|0.39     |-7.89|
|0.25     |-7.64|
|0.65     |-6.99|
|0.09     |-6.9 |
|-0.32    |-7.22|
|-0.4     |-7.62|

But the expected is:

|variation|stock|
|---------|-----|
|-7.34    |0    |
|-1.81    |0    |
|-0.51    |0    |
|17.19    |17.19|
|-1.63    |15.55|
|2.82     |18.37|
|-1.00    |17.37|
|0.56     |17.93|
|-17.92   |0    |
|0.34     |0.33 |
|1.02     |1.36 |
|0.39     |1.75 |
|0.25     |2    |
|0.65     |2.65 |
|0.09     |2.74 |
|-0.32    |2.42 |
|-0.40    |2.02 |

Thanks in advance.


回答1:


You may employ the array_agg() trick. It is not as scalable as a native function though.

CREATE TEMP FUNCTION special_sum(x ARRAY<FLOAT64>)
RETURNS FLOAT64
LANGUAGE js
AS """
  var sum = 0;
  for (const num of x)
  {
    sum += num;
    if (sum < 0)
    {
      sum = 0;
    }
  }
  return sum;
""";

with stock as (
SELECT -7.34 variation, UNION ALL
SELECT -1.81 UNION ALL
SELECT -0.51 UNION ALL
SELECT 17.19 UNION ALL
SELECT -1.63 UNION ALL
SELECT 2.82 UNION ALL
SELECT -1.00 UNION ALL
SELECT 0.56 UNION ALL
SELECT -17.92 UNION ALL
SELECT 0.34 UNION ALL
SELECT 1.02 UNION ALL
SELECT 0.39 UNION ALL
SELECT 0.25 UNION ALL
SELECT 0.65 UNION ALL
SELECT 0.09 UNION ALL
SELECT -0.32 UNION ALL
SELECT -0.40 
)
select variation, 
 special_sum( array_agg(variation) over (rows unbounded preceding) ) as stock 
from stock

The output is pretty close to what you provided:



来源:https://stackoverflow.com/questions/65775512/its-possible-to-create-a-rule-in-preceding-rows-in-sum

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!