BigQuery UPDATE 嵌套数组字段

Posted

技术标签:

【中文标题】BigQuery UPDATE 嵌套数组字段【英文标题】:BigQuery UPDATE nested array field 【发布时间】:2018-05-04 14:02:26 【问题描述】:

我需要使用另一个表中的值更新一个表中的嵌套字段。 使用this solution 我想出了一些可行的方法,但并不完全符合我的要求。 这是我的解决方案:

#standardSQL
UPDATE
  `attribution.daily_sessions_20180301_copy1` AS target
SET
hits = ARRAY(
  SELECT AS STRUCT * REPLACE(ARRAY(
    SELECT AS STRUCT *
    FROM(
      SELECT AS STRUCT * REPLACE(map.category AS productCategoryAttribute) FROM UNNEST(product))) AS product) FROM UNNEST(hits)
)
FROM
  `attribution.attribute_category_map`
AS map
WHERE
  (
    SELECT REPLACE(LOWER(prod.productCategory), 'amp;', '') FROM UNNEST(target.hits) AS h,
    UNNEST(h.product) AS prod LIMIT 1) = map.raw_name

attribute_category_map 是一个有两列的表,我在其中查找第 1 列中的对应值,并用第 2 列中的值替换目标表中的数据。我取得的最佳结果 - 用相同的值更新了一行上的所有嵌套字段,这是仅对第一个嵌套字段更正,而不是使用特定值更新每个嵌套字段。

主表的简化架构:

[  
     
      "name":"sessionId",
      "type":"STRING",
      "mode":"NULLABLE"
   ,
     
      "name":"hits",
      "type":"RECORD",
      "mode":"REPEATED",
      "fields":[  
           
            "name":"product",
            "type":"RECORD",
            "mode":"REPEATED",
            "fields":[  
                 
                  "name":"productCategory",
                  "type":"STRING",
                  "mode":"NULLABLE"
               ,
                 
                  "name":"productCategoryAttribute",
                  "type":"STRING",
                  "mode":"NULLABLE"
               
            ]
         
      ]
   
]

会话行中通常有多个匹配,一个匹配中有多个产品。值看起来像那些(如果你取消嵌套):

-----------------------------------------------------------------------------
sessionId | hits.product.productCategory| hit.product.productCategoryAttribute
-----------------------------------------------------------------------------
1         | automotive chemicals        | null
1         | automotive tools            | null
1         | null                        | null
2         | null                        | null
2         | automotive chemicals        | null
2         | null                        | null
3         | null                        | null
3         | bed accessories             | null
4         | null                        | null
4         | null                        | null
4         | automotive chemicals        | null
4         | null                        | null
-----------------------------------------------------------------------------

映射表的架构:

[  
     
      "name":"raw_name",
      "type":"STRING",
      "mode":"NULLABLE"
   ,
     
      "name":"category",
      "type":"STRING",
      "mode":"NULLABLE"
   
]

具有这样的值:

---------------------------------------------------
raw_name              |category                   |
---------------------------------------------------
automotive chemicals  |d1y2 - automotive chemicals|
automotive paint      |dijf1 - automotive paint   |
automotive tools      |efw1 - automotive tools    |
baby & infant toys    |wwfw - baby & infant toys  |
batteries & power     |fdsv- batteries & power    |
bed accessories       |0k77 - bed accessories     |
bike racks            |12df - bike racks          |
--------------------------------------------------

我想要的结果:

-----------------------------------------------------------------------------
    sessionId | hits.product.productCategory| hit.product.productCategoryAttribute
-----------------------------------------------------------------------------
    1         | automotive chemicals        | d1y2 - automotive chemicals
    1         | automotive tools            | efw1 - automotive tools
    1         | null                        | null
    2         | null                        | null
    2         | automotive chemicals        | d1y2 - automotive chemicals
    2         | null                        | null
    3         | null                        | null
    3         | bed accessories             | 0k77 - bed accessories
    4         | null                        | null
    4         | null                        | null
    4         | automotive chemicals        | d1y2 - automotive chemicals
    4         | null                        | null
    -----------------------------------------------------------------------------

我需要从主表中取值 productCategory,在 map 表中的 raw_name 列中查找,从列类别中取值并将其放入主表的 productCategoryAttribute 列。主要问题是目标字段是双重嵌套的,我不知道如何直接加入它们。

【问题讨论】:

您的查找所基于的主表中的列是什么?您还应该在主表上提供一些详细信息,并提供输入数据和预期数据的简化模式和示例。所以我们实际上可以帮助你:o) 您对数组中的每个元素使用相同的 map.category,因此预计数组中的所有元素都是相同的。正如 Mikhail 已经说过的,查看一些示例数据、您获得的结果以及您想要获得的结果会非常有帮助。 @MikhailBerlyant,我添加了一些细节,现在更清楚了吗? @Daria,我得到了这个“数组中每个元素的相同 map.category”部分,我意识到这是问题所在,我只是无法更接近正确的查询。我在上面添加了一些细节。 【参考方案1】:

以下已测试! 保持整个表的架构/数据不变,仅根据各自的映射更新 productCategoryAttribute 的值

#standardSQL
UPDATE `project.dataset.your_table` t
SET hits = 
  ARRAY(
    SELECT AS STRUCT * REPLACE(
      ARRAY(
        SELECT AS STRUCT product.* REPLACE(
          CASE WHEN map.raw_name = product.productCategory THEN category 
            ELSE productCategoryAttribute END AS productCategoryAttribute)
        FROM UNNEST(product) product
        LEFT JOIN UNNEST(agg_map.map) map 
        ON map.raw_name = product.productCategory
      ) AS product)
    FROM UNNEST(hits) hit
  ) 
FROM (SELECT ARRAY_AGG(row) map FROM `project.dataset.map` row) agg_map 
WHERE TRUE   

注意:上述解决方案假设映射表没有那么大,因为它依赖于将整个映射表聚合到一个数组中

【讨论】:

谢谢!它按预期工作。但是对于更大的目标表发生错误 - 错误:查询执行期间超出资源:无法在分配的内存中执行查询。用于 UPDATE 的排序运算符使用了太多内存。映射表只有约 400 对,所以我认为这不是问题。也许我可以限制最终 WHERE 子句中处理的数据量?

以上是关于BigQuery UPDATE 嵌套数组字段的主要内容,如果未能解决你的问题,请参考以下文章

如何在存储为字符串的 bigquery 字段中取消嵌套多个数组?

如何在BigQuery中创建嵌套字段和数组的数组

如何在 BigQuery 中取消嵌套多个数组?

BigQuery 嵌套表 UPDATE 基于非嵌套数据和嵌套数据的条件

在 BigQuery 中更新结构

Unnest 2 级别 - Big Query 数组