JSON 数组上的 BigQuery Enumerate-like 函数

Posted

技术标签:

【中文标题】JSON 数组上的 BigQuery Enumerate-like 函数【英文标题】:BigQuery Enumerate-like function on JSON Array 【发布时间】:2019-06-12 08:51:34 【问题描述】:

我想将 JSON 编码列表转换为原生 BigQuery 数组,理想情况下,这最终会是一个包含值、位置条目的元组或字典列表。因此引用了 python 枚举功能。

[(idx, elem) for idx, elem in enumerate(json_list_string)]

['pos':idx, 'value':elem for idx, elem in enumerate(json_list_string)]

将 json 转换为数组的第一部分我已经使用 question 解决了

编辑:

WITH
  my_ids AS (
  SELECT 'xyz' as grp, '["7f9f98fh9g4ef393d3h5", "chg3g33f26949hg6067d", "g477e5973ec04g7c3232", "0de1ec83304d761he786", "3c1h1f153530g90g35c2", "946637g145h48322686f"]' as ids
  UNION ALL
  SELECT 'abc' as grp, '["7f9f98fh9g4ef393d3h5", "chg3g33fdsfsdfs49hg6067d", "g477e5973ec04g7c3232", "0de1ec83304d761he786", "3c1h1f153530g90g35c2", "946637g145h48322686f"]' as ids
  )

SELECT
  *
FROM my_ids

在理想的世界中,我会得到如下输出:

xyz, 7f9f98fh9g4ef393d3h5, 1
xyz, chg3g33f26949hg6067d, 2
...
abc, 946637g145h48322686f, 6

请注意,列表可能很长(最多 24 个条目,我有点不想硬编码所有路径)

Edit2:(可能的解决方案)

WITH
  my_ids AS (
  SELECT 'xyz' as grp, '["7f9f98fh9g4ef393d3h5", "chg3g33f26949hg6067d", "g477e5973ec04g7c3232", "0de1ec83304d761he786", "3c1h1f153530g90g35c2", "946637g145h48322686f"]' as ids
  UNION ALL
  SELECT 'abc' as grp, '["7f9f98fh9g4ef393d3h5", "chg3g33fdsfsdfs49hg6067d", "g477e5973ec04g7c3232", "0de1ec83304d761he786", "3c1h1f153530g90g35c2", "946637g145h48322686f"]' as ids
  ),

  as_list AS (SELECT
    *,
    SPLIT(REGEXP_REPLACE(JSON_EXTRACT(ids,'$'), r'[\[\]\"]', ''), ',') AS split_items,
    GENERATE_ARRAY(1, ARRAY_LENGTH(SPLIT(REGEXP_REPLACE(JSON_EXTRACT(ids,'$'), r'[\[\]\"]', ''), ','))) AS positions
  FROM my_ids)

SELECT grp, ids, positions[OFFSET(off)] as pos
FROM as_list, unnest(split_items) as ids WITH OFFSET off

【问题讨论】:

请提供输入和所需输出的简化示例以及有关您要查找的查询类型的更多详细信息 @MikhailBerlyant 已更新,是否更清楚? 只需发布您的解决方案作为答案!或者它仍然不是你想要的? @MikhailBerlyant 是的,我想我会这样做。想知道是否有更自然的方式来实现我想要的。这感觉有点难看:D 我可以看到另一个不那么冗长的选项 - 将很快发布...发布! 【参考方案1】:

以下是 BigQuery 标准 SQL

#standardSQL
WITH `project.dataset.my_ids` AS (
  SELECT 'xyz' AS grp, '["7f9f98fh9g4ef393d3h5", "chg3g33f26949hg6067d", "g477e5973ec04g7c3232", "0de1ec83304d761he786", "3c1h1f153530g90g35c2", "946637g145h48322686f"]' AS ids UNION ALL
  SELECT 'abc' AS grp, '["7f9f98fh9g4ef393d3h5", "chg3g33fdsfsdfs49hg6067d", "g477e5973ec04g7c3232", "0de1ec83304d761he786", "3c1h1f153530g90g35c2", "946637g145h48322686f"]' AS ids
)
SELECT grp, id, ROW_NUMBER() OVER(PARTITION BY grp ORDER BY OFFSET) pos
FROM `project.dataset.my_ids`, 
UNNEST(SPLIT(REGEXP_REPLACE(JSON_EXTRACT(ids,'$'), r'[\[\]\"]', ''), ',')) id WITH OFFSET

【讨论】:

确实更干净,有趣的是,在转向抵消之前,我确实有一个这样的版本。将此逻辑应用于 ~60GB 时,我一直遇到资源超出错误。我的管道中有另一个窗口函数,它现在也导致资源超出问题。所以我不能肯定地说。您能谈谈这两种方法在资源使用方面的比较吗? 知道如何克服 over 函数超出的资源吗?我记得在我的脑海里,有一些关于双重​​分区的东西。 在 cmets 中完全不可能回答这个问题 - 我建议您发布带有特定用例和所有相关细节的新问题,以便我们为您提供帮助 以下不是更干净吗?我将很快写下后续问题。 SELECT grp, id, pos + 1 as pos FROM project.dataset.my_ids, UNNEST(SPLIT(REGEXP_REPLACE(JSON_EXTRACT(ids,'$'), r'[[]\"]', ''), ',')) id WITH OFFSET 作为 pos 或只是接受,索引是从零开始的,本质上“WITH OFFSET”是我最初要求的!! 这是一个独立的问题顺便说一句:***.com/questions/56565523/…

以上是关于JSON 数组上的 BigQuery Enumerate-like 函数的主要内容,如果未能解决你的问题,请参考以下文章

Bigquery:是不是有一种 json 路径方法可以仅从具有动态键的 json 数组中提取值?

如何从 BigQuery 中的 JSON 字符串中提取数组

如何计算位于 BigQuery 表中的 json 数组中的对象数?

Bigquery:从 json 数组中提取数据

BigQuery concat 嵌套数组 json

从 BigQuery 中的 JSON 数组中提取多个值