如何更改 BigQuery 重复记录的 col 类型

Posted

技术标签:

【中文标题】如何更改 BigQuery 重复记录的 col 类型【英文标题】:How to change the col type of a BigQuery repeated record 【发布时间】:2019-04-03 00:16:54 【问题描述】:

我正在尝试将重复记录的 col 类型从 STRING 更改为 TIMESTAMP。这里有 BQ 文档的一些建议 (manually-changing-schemas)。但是,我遇到的每个推荐建议都有问题。

这是一个示例架构:


  'name' => 'id',
  'type' => 'STRING',
  'mode' => 'REQUIRED'
,

  'name' => 'name',
  'type' => 'STRING',
  'mode' => 'REQUIRED'
,
// many more fields including nested records and repeated records

  'name' => 'locations',
  'type' => 'RECORD',
  'mode' => 'REPEATED',
  'fields' => [
    
      'name' => 'city',
      'type' => 'STRING',
      'mode' => 'REQUIRED'
    ,
    
      'name' => 'updated_at',
      'type' => 'STRING',   // ** want this as TIMESTAMP **
      'mode' => 'REQUIRED'
    ,
  ]

使用查询的问题:

我认为我们必须 UNNEST 重复记录,将字段转换为每个重复记录的时间戳,然后以某种方式重新创建行以插入新表。

将表格导出为 JSON 的问题:

当以 JSON 格式导出表格时,它会导出数据的原始 json 表示形式(如我们所料,带有地图和字典)。

但是,我们无法将该原始数据导入回 BQ:

BigQuery 不支持 JSON 格式的地图或字典。例如, "product_categories": "my_product": 40.0 无效,但是 "product_categories": "column1": "my_product" , "column2": 40.0 是 有效。

https://cloud.google.com/bigquery/docs/loading-data-cloud-storage-json#limitations

任何建议将不胜感激!

【问题讨论】:

【参考方案1】:

以下答案基于:BigQuery StandardSQL 中的REPEATED RECORD 类型表示为ARRAY<STRUCT<f1 f1_type, f2 f2_type ... >> 类型。

这不是我最喜欢的,因为您必须指定完整的列列表。也许有更好的方法。

#standardSQL
-- Build sample data, try to mimic what's in question.
CREATE OR REPLACE TABLE
  <your_dataset>.sample_table AS
SELECT name, 
       array<struct<city string, update_at string>>[("SFO", "2011-1-1"), ("SEA", "2022-2-2")] 
       as locations
FROM UNNEST(['Name1', "Name2", "Name3"]) as name;

然后下面的 SQL 会将 update_at 列转换为 DATE 并保存到新表(如果您愿意,也可以保存到同一个表)。

#standardSQL
CREATE OR REPLACE TABLE
  <your_dataset>.output_table AS
SELECT * REPLACE (
   ARRAY(SELECT AS STRUCT * REPLACE(CAST(update_at AS DATE) AS update_at)
         FROM UNNEST(locations)) 
   AS locations 
   )
FROM
  <your_dataset>.sample_table;

【讨论】:

感谢您的详细回复。在我的示例代码中,我过度简化了数据模型;我们正在处理的重复记录有 30 多个字段....我想我只需要硬着头皮为所有字段重新制作所有类型 祝你好运@harlow,我也在寻找更好的解决方案。但是 30+ 的领域没什么大不了的,我猜你可能已经完成了工作。 @harlow,我更新了我的答案,您可以在底部找到更好的解决方案。 好的,谢谢。那好多了!新表不幸丢失的一件事是新表输出中的NOT NULL ('mode' => 'REQUIRED') 约束。即 idname 我们在上一个表中是必需的,但生成这些的新表不是必需的 @harlow,我找到了如何完全避免指定列列表的答案。请查看更新。但它仍然不保留“必需”信息。

以上是关于如何更改 BigQuery 重复记录的 col 类型的主要内容,如果未能解决你的问题,请参考以下文章

如何通过删除基于 8 列中的 2 列的重复项来清理 BigQuery 表?

BigQuery:如何从重复记录中仅提取某些字段作为另一个重复字段

如何使用 bigrquery 库将非重复记录插入 BigQuery?

如何将 Bigquery 重复记录转换为列?

如何在 BigQuery 中取消嵌套重复记录,一个数组给出列名,另一个给出列值?

BigQuery - 使用更改/删除的记录更新表