可以在前面的行中创建一条规则吗?

Posted

技术标签:

【中文标题】可以在前面的行中创建一条规则吗?【英文标题】:It's possible to create a rule in preceding rows in sum? 【发布时间】:2021-01-18 13:32:21 【问题描述】:

我有一个历史库存变化值,必须计算库存值。但我也有一个规则,即 stock 为 max(stock, 0),或者换句话说,如果 stock 为负数,我认为它为零。

要在 Big Query 中做到这一点,我认为方法是这样的:

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

我认为解决方案类似于说前面必须是 max(preceding, 0)。但我没有找到如何做到这一点。

我查询得到的结果是:

|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|

但预期是:

|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 |

提前致谢。

【问题讨论】:

我认为没有一种方法可以在不使用循环的情况下在 BigQuery 中编写此代码 - 即非常昂贵。 【参考方案1】:

您可以使用 array_agg() 技巧。但它的可扩展性不如原生函数。

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

输出与您提供的非常接近:

【讨论】:

谢谢@Yun Zhang,这很好!当然,性能是海量数据的问题。但这在这里解决了很多。 我最近不得不实施同样的解决方案。您提到它不像本机功能那样可扩展。是否存在其他更具可扩展性的解决方案?

以上是关于可以在前面的行中创建一条规则吗?的主要内容,如果未能解决你的问题,请参考以下文章

Exchange 2013 创建一条邮箱用户限制策略

Exchange 2013 创建一条邮箱用户限制策略

html 在svg中创建一条路径

在 golang 中创建一片缓冲通道

motion分析虚拟弹簧可以显示吗

Pentaho行变量