输入数据集:
日期 | 身份证 | 数量 | 想要的 |
---|---|---|---|
2020-01-01 | 1 | 8 | 8 |
2020-01-02 | 1 | 11.5 | 19.5 |
2020-01-03 | 1 | -20 | 0 |
2020-01-04 | 1 | 10 | 10 |
2020-01-05 | 1 | -5 | 5 |
2020-01-06 | 2 | -9 | 0 |
2020-01-07 | 2 | 26 | 26 |
2020-01-08 | 2 | 5 | 31 |
2020-01-09 | 2 | -23 | 8 |
2020-01-10 | 2 | -10.5 | 0 |
2020-01-11 | 2 | 5 | 5 |
我正在尝试创建一个自定义运行总计,每当运行总计低于 0 时,该总计都会重置为 0。
我的代码
CREATE TEMP FUNCTION conditional_sum(X ARRAY<FLOAT64>)
RETURNS FLOAT64
LANGUAGE js as r"""
if (!('sum' in this)) this.sum =0
return this.sum = (X + this.sum) <0 ? 0 : this.sum + X
""";
select *,conditional_sum(array_agg(number) over (partition by ID order by Date)) as run_sum from tbl
我得到的错误是
Failed to coerce output value "11.5,-20" to type FLOAT64. Bad double value
我从运行正数和负数的总和,其中总和不能低于零借用了这段代码,并且在没有窗口函数和arrary_agg的情况下它也能很好地工作。但我需要窗口函数,因为我需要将条件总和应用于 Bigquery SQL 中的多个 ID
其他 udf 错误不处理窗口函数
请在 JavaScript 代码中添加 for 循环。仅生成当前行的数组。
CREATE TEMP FUNCTION conditional_sum(X ARRAY<FLOAT64>)
RETURNS FLOAT64
LANGUAGE js as r"""
var cur=0;
var out=[];
for(let x of X){
cur+=x*1;
if(cur<0) cur=0;
//out.push(cur)
}
return cur;
// return out;
""";
With tbl as (
SELECT '2020-01-01' AS Date, 1 AS ID, 8 AS Number, 8 AS Desired
UNION ALL SELECT '2020-01-02', 1, 11.5, 19.5
UNION ALL SELECT '2020-01-03', 1, -20, 0
UNION ALL SELECT '2020-01-04', 1, 10, 10
UNION ALL SELECT '2020-01-05', 1, -5, 5
UNION ALL SELECT '2020-01-06', 2, -9, 0
UNION ALL SELECT '2020-01-07', 2, 26, 26
UNION ALL SELECT '2020-01-08', 2, 5, 31
UNION ALL SELECT '2020-01-09', 2, -23, 8
UNION ALL SELECT '2020-01-10', 2, -10.5, 0
UNION ALL SELECT '2020-01-11', 2, 5, 5
)
select *,conditional_sum([1.1,2,1]),
string_agg(cast(number as float64) || '' ) over win1,
conditional_sum(array_agg(cast(number as float64)) over win1 ) as run_sum
from tbl
window win1 as (partition by ID order by Date rows between unbounded preceding and current row)