0

我正在尝试使用 SQL 在 BigQuery 中构建一个数据结构,该结构完全反映了我在上传 JSON 时获得的数据结构。这将使我能够使用带有点表示法的 SQL 来查询视图,而不必使用 UNNEST,我确实理解这一点,但我的许多客户发现非常混乱和不直观。

如果我用几行构建一个非常简单的虚拟数据集,然后使用 ARRAY_AGG(STRUCT([field list])) 模式嵌套:


    WITH
      flat_table AS (
      SELECT "BigQuery" AS name, 23 AS user_count, "Data Warehouse" AS data_thing, 5 AS ease_of_use, "Awesome" AS description UNION ALL
      SELECT "MySQL" AS name, 12 AS user_count, "Database" AS data_thing, 3 AS ease_of_use, "Solid" AS description
      )

    SELECT 
    name, user_count, 
    ARRAY_AGG(STRUCT(data_thing, ease_of_use, description)) AS attributes
    FROM flat_table 
    GROUP BY name, user_count

然后保存并查看架构显示该attributes字段是Type = RECORDand Mode = REPEATED。架构字段名称是:


name                    
    user_count              
    attributes          
    attributes.data_thing   
    attributes.ease_of_use  
    attributes.description 

如果我查看 INFORMATION_SCHEMA.COLUMNS 查询中的 COLUMN 信息,我可以看到该attributes字段is_nullable = NOdata_type = ARRAY<STRUCT<data_thing STRING, ease_of_use INT64, description STRING>>

如果我想查询这个结构,我需要使用 UNNEST 模式,如下所示:


    SELECT
      name,
      user_count
    FROM
      nested_table,
      UNNEST(attributes)
    WHERE
      ease_of_use > 3

但是,当我使用自动架构检测将相同数据的以下 JSON 表示上传到 BigQuery 时:


    {"attributes":{"description":"Awesome","ease_of_use":5,"data_thing":"Data Warehouse"},"user_count":23,"name":"BigQuery"}
    {"attributes":{"description":"Solid","ease_of_use":3,"data_thing":"Database"},"user_count":12,"name":"MySQL"}

加载后,模式看起来几乎相同,除了attributes字段是Mode = NULLABLE(它仍然是Type = RECORD)。INFORMATION_SCHEMA.COLUMNS 向我显示该attributes字段现在是is_nullable = YES and data_type = STRUCT<data_thing STRING, ease_of_use INT64, description STRING>,即现在可以为空且不在数组中。

然而对我来说最有趣的是我现在可以使用点符号而不是 UNNEST 模式来查询这个表,所以上面的查询变成了:


    SELECT
      name,
      user_count
    FROM
      nested_table_json
    WHERE
      attributes.ease_of_use > 3

即使在这种微不足道的情况下,这也可以说更容易阅读。然而,一旦我们得到具有多个嵌套字段和多级嵌套的更复杂的数据结构,UNNEST 模式就变得极其难以编写、QA 和调试。点符号模式似乎更加直观和可扩展。

所以我的问题是:是否可以通过在 SQL 中编写查询来构建与加载的 JSON 等效的数据结构,使我们能够使用点表示法构建标准 SQL 查询并且不需要复杂的 UNNEST 模式?

4

1 回答 1

1

如果您知道您的 array_agg 将产生一行,则可以像这样删除 ARRAY 符号:

SELECT 
    name, user_count, 
    ARRAY_AGG(STRUCT(data_thing, ease_of_use, description))[offset(0)] AS attributes

注意使用OFFSET(0)这种方式返回的输出将是:

[
  {
    "name": "BigQuery",
    "user_count": "23",
    "attributes": {
      "data_thing": "Data Warehouse",
      "ease_of_use": "5",
      "description": "Awesome"
    }
  }
]

可以使用点表示法查询。

如果您只想将结果分组STRUCT,则不需要array_agg.

WITH
      flat_table AS (
      SELECT "BigQuery" AS name, 23 AS user_count, struct("Data Warehouse" AS data_thing, 5 AS ease_of_use, "Awesome" AS description) as attributes UNION ALL
      SELECT "MySQL" AS name, 12 AS user_count, struct("Database" AS data_thing, 3 AS ease_of_use, "Solid" AS description)
      )

    SELECT 
    *
    FROM flat_table 
于 2019-10-03T10:33:32.760 回答