Google bigquery BigQuery-股票分类账的窗口

Google bigquery BigQuery-股票分类账的窗口,google-bigquery,Google Bigquery,我想我有一个有趣的窗口场景,与网站库存可用性跟踪相关,可以用标准SQL进行处理。这是试图根据从给定产品的“现有”库存量推拉的事件,构建一个随时间变化的库存头寸视图 我们有3种与此问题相关的事件类型: StocklevelUpdated PUSH:每晚午夜,我们都会从仓库获得给定产品的onHandQty可用性级别的新更新。如果每种产品的onHandQty作为第二天交易的新值计算,这基本上是一个硬“重置”。注意:这实际上每晚发送一条记录,即使没有变化 OrderAccepted PULL:然后在一天

我想我有一个有趣的窗口场景,与网站库存可用性跟踪相关,可以用标准SQL进行处理。这是试图根据从给定产品的“现有”库存量推拉的事件,构建一个随时间变化的库存头寸视图

我们有3种与此问题相关的事件类型:

StocklevelUpdated PUSH:每晚午夜,我们都会从仓库获得给定产品的onHandQty可用性级别的新更新。如果每种产品的onHandQty作为第二天交易的新值计算,这基本上是一个硬“重置”。注意:这实际上每晚发送一条记录,即使没有变化

OrderAccepted PULL:然后在一天中,有许多产品的“OrderAccepted”事件,在这种情况下,股票“onHandQtyDelta”现在的售价为负值-订购的产品的2个单位为2

订单取消:产品的数量也可以取消,这对于“onHandQtyDelta”具有正值,因为它添加回可供销售的库存中

下面是一个稍微简化的数据版本的tabluar视图,按照我想要实现的时间顺序。注意:这显示了一个单一的产品,当然还有很多

onHandQtyDelta—此事件导致的onHandQty更改

onHandQty-这是在delta影响后该时间点的净正值

现在,尽管上图显示了所有的值,但是注释29是其中一个午夜重置,实际上,并非所有这些数据都可用,并且需要为每个订单事件类型导出一个值。i、 e1缺失

onHandQty:实际数据集中唯一定义了绝对onHandQty的行是“StocklevelUpdated”事件。本质上,这将在午夜“重置”产品的该值,例如29。日志记录基本上需要追溯到最近的一个。但是,需要派生onHandQtyDelta

onHandQtyDelta只有OrderAccepts和OrderCancelled事件具有此值,该值需要用于计算onHandQty

因此,一张图片可以表达千言万语,因此要处理的数据的真实情况如下所示:

如果有1000万行这样做,如何有效地执行此操作

我的想法是使用窗口和'lag'函数回顾以前记录的onHandQty值,看看它是什么,然后进行加法或减法运算,得出新的onHandQty值

然后,问题是一个递归问题,因为上一个事件本身需要回顾其上一个事件,依此类推……直到您到达stocklevelUpdated事件,因为这是唯一一个具有实际值的事件,因此需要向前处理。但是,当您不知道要返回多长时间才能得到这样的事件时,如何使用窗口来实现这一点?可以是任意数量的OrderAccepts和Cancels,也可以是none

也许有一些聪明的数组,将给定的产品行收集到一个数组中,并执行一些数组agg函数

我想我已经有了stuckon的想法,窗口是一种方式,可能会被一个简单的解决方案所蒙蔽!对于所有的细节,我很抱歉,但我不想含糊其辞地说我需要什么帮助

下面给出了要处理的开始测试数据集,我只是按产品和时间对其进行了排序,以便创建图像

WITH stock_changes AS (
SELECT
  "StocklevelUpdated" AS eventName, 
  Timestamp("2017-06-29T23:59:59") AS stockLevelEventAt,
  "PRODUCT_190035001612" AS productId,
  null AS onHandQtyDelta,
  23 AS onHandQty
UNION ALL (
SELECT
  "StocklevelUpdated" AS eventName, 
  Timestamp("2017-06-29T23:59:59") AS stockLevelEventAt,
  "PRODUCT_4545423454545" AS productId,
  null AS onHandQtyDelta,
  120 AS onHandQty)
UNION ALL (
  SELECT 
  "OrderAccepted" AS eventName, 
  Timestamp("2017-06-30T01:02:20") AS stockLevelEventAt,
  "PRODUCT_190035001612" AS productId,
  -2 AS onHandQtyDelta,
  null AS onHandQty)
UNION ALL (
  SELECT 
  "OrderAccepted" AS eventName, 
  Timestamp("2017-06-30T02:19:20") AS stockLevelEventAt,
  "PRODUCT_190035001612" AS productId,
  -3 AS onHandQtyDelta,
  null AS onHandQty)
UNION ALL (
  SELECT 
  "OrderAccepted" AS eventName, 
  Timestamp("2017-06-30T05:13:20") AS stockLevelEventAt,
  "PRODUCT_4545423454545" AS productId,
  -3 AS onHandQtyDelta,
  null AS onHandQty)
UNION ALL (
  SELECT 
  "OrderCancelled" AS eventName, 
  Timestamp("2017-06-30T13:02:20") AS stockLevelEventAt,
  "PRODUCT_190035001612" AS productId,
  +2 AS onHandQtyDelta,
  null AS onHandQty)
UNION ALL (
  SELECT 
  "OrderCancelled" AS eventName, 
  Timestamp("2017-06-30T11:02:20") AS stockLevelEventAt,
  "PRODUCT_4545423454545" AS productId,
  2 AS onHandQtyDelta,
  null AS onHandQty)
UNION ALL (
SELECT
  "StocklevelUpdated" AS eventName, 
  Timestamp("2017-06-30T23:59:59") AS stockLevelEventAt,
  "PRODUCT_190035001612" AS productId,
  null AS onHandQtyDelta,
  29 AS onHandQty)
UNION ALL (
SELECT
  "StocklevelUpdated" AS eventName, 
  Timestamp("2017-06-30T23:59:59") AS stockLevelEventAt,
  "PRODUCT_4545423454545" AS productId,
  null AS onHandQtyDelta,
  140 AS onHandQty)
)
SELECT *
FROM stock_changes
order by productId, stockLevelEventAt ASC

下面是BigQuery标准SQL

标准SQL 随着库存的变化 选择StocklevelUpdated作为eventName,TIMESTAMP2017-06-29T23:59:59作为stockLevelEventAt, PRODUCT_190035001612作为productId,NULL作为onHandQtyDelta,23作为onHandQty UNION ALL 选择StocklevelUpdated,TIMESTAMP2017-06-29T23:59:59,PRODUCT_45423454545,NULL,120 UNION ALL 选择OrderAccepted,TIMESTAMP2017-06-30T01:02:20,PRODUCT_190035001612,-2,NULL UNION ALL 选择OrderAccepted,TIMESTAMP2017-06-30T02:19:20,PRODUCT_190035001612,-3,NULL UNION ALL 选择OrderAccepted,TIMESTAMP2017-06-30T05:13:20,PRODUCT_45423454545,-3,NULL UNION ALL 选择OrderCancelled,TIMESTAMP2017-06-30T13:02:20,PRODUCT_190035001612,+2,NULL UNION ALL 选择OrderCancelled,TIMESTAMP2017-06-30T11:02:20,PRODUCT_454234545,2,NULL UNION ALL 选择StocklevelUpdated,TIMESTAMP2017-06-30T23:59:59,PRODUCT_190035001612,NULL,29 UNION ALL 选择StocklevelUpdated,TIMESTAMP2017-06-30T23:59:59,PRODUCT_45423454545,NULL,140 选择 eventName、stockLevelEventAt、productId、, 增量为onHandQtyDelta、IFNULLonHandQty、onHandQty为onHandQty 从…起 选择*, SUMIFNULLonHandQty,0-增量 按productId、格式\u时间戳“%Y-%m-%d”、stockLevelEventAt超额分配 按库存级别事件在DESC订购 无界前置和1前置之间的行,如现有 从…起 选择eventName、stockLevelEventAt、productId、onHandQty、, 案例 当prev为NULL时,则为IFNULLo nHandQtyDelta,0 ELSE onHandQty-上一个-增量 以三角形结束 从…起 选择*, SUMIFNULLonHandQtyDelta,0按productId超额分配,格式为\u时间戳“%Y-%m-%d”,StockLevelEventAtOrder按stockLevelEventAt作为增量, LagenhandQuantity按productId超额分配,eventName按stockLevelEventAt超额分配 从库存变化 按productId、stockLevelEventAt ASC排序的订单 结果如下

行事件名称stockLevelEventAt productId onHandQtyDelta onHandQty 1库存水平更新2017-06-29 23:59:59 UTC产品_190035001612 0 23 2接受订单2017-06-30 01:02:20 UTC产品_190035001612-2 21 3接受订单2017-06-30 02:19:20 UTC产品_190035001612-3 18 4订单取消2017-06-30 13:02:20 UTC产品_190035001612 20 5库存水平更新2017-06-30 23:59:59 UTC产品_190035001612 9 29 6库存水平更新2017-06-29 23:59:59 UTC产品_45423450 120 7接受订单2017-06-30 05:13:20 UTC产品_45423454545-3 117 8订单取消2017-06-30 11:02:20 UTC产品_4542345452 119 9库存水平更新2017-06-30 23:59:59 UTC产品_45423454521 140
最有可能的是可以进一步优化-但我更关注逻辑的实现,而不是优化

Mikhail哇谢谢你-我现在需要坐下来消化一下,非常感谢。首先得到正确的结果显然是一个很好的开始,然后可以优化大约1200万行,这是肯定的。顺便说一句,这个查询很有可能扩展到数百万行的真实数据,这取决于您的productID/天/等分布。你只要试一下:哦,如果你觉得知道这个很好,别忘了接受并投票!只需使用完整的数据集检查SQL。如果存在另一列“location”2值、“UK”或“US”,其中事实上productId+location是唯一的,而不仅仅是productId,即相同的productId,不同的location,这会发生什么变化?我想我把位置添加到分区和orderby中是对的,但我只是想检查一下?此外,有时我们会超卖,因此onHandQty可能会变为负值之前为0,然后我们创建了一个订单,然后变为负值……目前它显示为“null”。太棒了,谢谢!我认为您只需要将位置添加到分区。根本不需要点菜