BigQuery:UNNEST()上的LAG()

时间:2018-10-12 14:52:15

标签: sql google-bigquery

我一直在使用LAG()返回ARRAY of STRUCT中上一行的值,并且{{1}似乎不支持LAG/LEAD之类的导航窗口功能}}。

这听起来不太理想,但是您需要UNNEST全部和(重新)UNNEST !!

例如说您要上一行的金额:

  

编辑:架构详细信息:

     

发票架构:PARTITION BY

     

预期输出:docID STRING, lines STRUCT<lineID STRING, amount NUMERIC>

docID STRING, lines STRUCT<lineID STRING, amount NUMERIC, prev_amount NUMERIC>

这非常慢。我希望我们可以通过某种方式将ARRAY作为窗口框架使用。

是否有其他选择??我正在使用SELECT docID, lineID, amount ,LAG(amount) OVER (PARTITION BY docID ORDER by lineID) prev_amount FROM invoices, UNNEST(lines) ,但这可能适用于其他DBMS。

  

更新:我使用BigQuery提出了以下替代方案。更快,也许这就是OFFSET的用途,这很丑陋,在我看来可能更简单。

WITH OFFSET

2 个答案:

答案 0 :(得分:1)

以下显示了更好的性能(至少是我为了快速测试而使用的少量)。执行计划看起来也更好(至少对我而言)

#standardSQL
SELECT 
   lines[OFFSET(pos)].*, lines[SAFE_OFFSET(pos - 1)].amount prev_amount
FROM invoices, UNNEST(GENERATE_ARRAY(0, ARRAY_LENGTH(lines) - 1)) pos

注意:我假设遵循模式[STRUCT<docID INT64, lineID INT64, amount FLOAT64>] lines

  

更新:调整为与您刚提供的真实架构相匹配

#standardSQL
SELECT docID, ARRAY(
    SELECT AS STRUCT 
      lines[OFFSET(pos)].*, 
      lines[SAFE_OFFSET(pos - 1)].amount prev_amount 
    FROM UNNEST(GENERATE_ARRAY(0, ARRAY_LENGTH(lines) - 1)) pos
    ) lines
FROM invoices

答案 1 :(得分:1)

在米哈伊尔的答案的下面,改用WITH OFFSET表现更好(55s比170s,超过5000万行)

#standardSQL
SELECT docID, ARRAY(
    SELECT AS STRUCT 
      l.*, 
      lines[SAFE_OFFSET(pos - 1)].amount prev_amount 
    FROM UNNEST(lines) l WITH OFFSET pos
    ) lines
FROM invoices

注意:如果将ORDER BYWHERE子句添加到更改原始索引的取消嵌套中,则此方法将无法按原样工作。

这是我的用例,如果您是在相对位置在过滤后的数组中定位,则应该先使用子查询来创建过滤后的数组,然后再使用组合UNNEST WITH OFFSET + OFFSET/ORDINAL在外部查询中。