0

这是我的数据的样子:

日期 库存单位 库存添加 要求
2021 年 11 月 22 日 XYZ 70 18
2021 年 11 月 23 日 XYZ 0 18
2021 年 11 月 24 日 XYZ 0 50
2021 年 11 月 25 日 XYZ 0 15
2021 年 11 月 26 日 XYZ 80 30
2021 年 11 月 27 日 XYZ 0 20
2021 年 11 月 28 日 XYZ 0 15
2021 年 11 月 29 日 XYZ 0 20
2021 年 11 月 30 日 XYZ 0 10
2021 年 12 月 1 日 XYZ 100 40
2021 年 12 月 2 日 XYZ 0 10

我想创建一个solution使用 BigQuery SQL 命名的新列,在第一行,即 2021 年 11 月 22 日,我希望公式为 - inventory_added - demand。这将给我第一行的值为solution52。

现在我不能做的是从第二行开始:所以,接下来,将是52 (remaining inventory from previous day) + 0 (inventory_added on 23rd Nov 2021) - 18 (demand on 23 Nov 2021). 这等于 34。

同样转到下一行,即 11 月 24 日:值 insolution将是34 + 0 - 50 = -16。现在因为它是负数,所以应该把它设为 0。

我试过这个 - MAX(solutions, 0)

结果将如下所示:

日期 库存单位 库存添加 要求 解决方案
2021 年 11 月 22 日 XYZ 70 18 52
2021 年 11 月 23 日 XYZ 0 18 34
2021 年 11 月 24 日 XYZ 0 50 0
2021 年 11 月 25 日 XYZ 0 15 0
2021 年 11 月 26 日 XYZ 80 30 50
2021 年 11 月 27 日 XYZ 0 20 30
2021 年 11 月 28 日 XYZ 0 15 15
2021 年 11 月 29 日 XYZ 0 20 0
2021 年 11 月 30 日 XYZ 0 10 0
2021 年 12 月 1 日 XYZ 100 40 60
2021 年 12 月 2 日 XYZ 0 10 50

我不确定这是否可以通过 BigQuery 完成,但欢迎提出所有建议。

谢谢!

4

2 回答 2

1

如果没有条件“它是否定的,它应该设为 0”,您可以使用SUM() 函数的窗口(在 BigQuery 术语中 - 分析)变体:

SELECT *, 
       SUM(inventory_added - demand) OVER (PARTITION BY sku ORDER BY date) AS solution
FROM source_table

在这种情况下,输出变为迭代,您必须使用递归 CTE(如果在 BigQuery 中可用)或迭代存储过程。


我看到递归 CTE 在 BigQuery 中不可用……您能否提供一个伪代码作为存储过程的起点?– 山塔努耆那教

CREATE PROCEDURE procname()
BEGIN
    CREATE temptable;
    OPEN CURSOR FOR SELECT * FROM datatable ORDER BY date;
    SET @solution = 0;
    FETCH CURSOR INTO @date, @sku, @inventory_added, @demand;
    LOOP    ​
       ​ SET @solution = GREATEST(@solution + @inventory_added - @demand, 0);
       ​ INSERT INTO temptable VALUES (@date, @sku, @inventory_added, @demand, @solution);
        FETCH CURSOR INTO @date, @sku, @inventory_added, @demand;
    UNTIL NO_ROWS_IN_CURSOR END LOOP;
    SELECT * FROM temptable;
    DROP temptable;
END
于 2021-11-23T13:07:35.953 回答
0

作为一种选择 - 考虑使用最近引入的FOR...IN循环

declare result int64;
declare prev_sku string;

create temp table results as (select *, 0 as solution from your_table where false);

set (result, prev_sku) = (0, '');
for record in (select *, parse_date('%d %B %Y', regexp_replace(date, r'(\d*)(\w*)( \w{3} \d{4})', r'\1 \3')) dt from your_table order by sku, dt) do
  if record.sku != prev_sku then set result = 0; end if;
  set result = result + record.inventory_added - record.demand;
  if result < 0 then set result = 0; end if;
  insert into results values(record.date, record.sku, record.inventory_added, record.demand, result);
  set prev_sku = record.sku;  
end for;
select * from results 
order by sku, parse_date('%d %B %Y', regexp_replace(date, r'(\d*)(\w*)( \w{3} \d{4})', r'\1 \3'));   

如果应用于您问题中的样本数据 - 输出是

在此处输入图像描述

注意:在提供预期结果的同时 - 显然这将非常慢(就像任何基于光标的解决方案一样) - 所以虽然适用于学习 - 我认为不适合实际生产使用

于 2021-11-24T22:15:25.543 回答