无法使用 google bigquery(标准)取消嵌套某些字段

Posted

技术标签:

【中文标题】无法使用 google bigquery(标准)取消嵌套某些字段【英文标题】:Unable to un-nest some fields using google bigquery (standard) 【发布时间】:2017-10-19 19:04:52 【问题描述】:

我有一个嵌套表,我无法访问使用标准 google bigquery 的所有字段。

例如这个查询失败

SELECT  *
FROM 
    (
    SELECT
           rev_info.user.id as player_id,
           rev_info.purchase.total.currency as currency,
           rev_info.purchase.total.amount as REV
          ,rev_info.purchase.virtual_items.items.sku     as sku 
    FROM `gcs.rev`
    )
WHERE currency = 'USD'

有错误

“错误:无法在 [9:59] 访问类型为 ARRAY> 的值的字段 sku”

然而

SELECT  *
FROM 
    (
    SELECT
           rev_info.user.id as player_id,
           rev_info.purchase.total.currency as currency,
           rev_info.purchase.total.amount as REV
          --,rev_info.purchase.virtual_items.items.sku   as sku 
    FROM `gcs.rev`
    )
WHERE currency = 'USD'

这个查询很好。

还要注意

SELECT
       rev_info.purchase.virtual_items.items.sku     as sku 
FROM `gcs.rev`

失败并出现与上述相同的错误。

【问题讨论】:

您所说的“无法取消嵌套...”是什么意思?你还没试过!至少从您的问题中的查询来看是这样的! 您好,欢迎来到 ***!如果您收到的答案对您有任何帮助或解决了您的问题,请考虑接受并投票,因为这在此论坛中很重要:***.com/help/someone-answers 【参考方案1】:

扩展 Elliott 的答案 - 我认为您首先需要 UNNEST,但随后您很可能需要汇总您的 sku。否则你会得到相当冗余(扁平化)的输出

我觉得下面是您可能需要的 - 它适用于 BigQuery 标准 SQL

#standardSQL
SELECT 
  player_id, 
  currency, 
  REV, 
  STRING_AGG(sku) SKUs
FROM (
  SELECT
    rev_info.user.id AS player_id,
    rev_info.purchase.total.currency AS currency,
    rev_info.purchase.total.amount AS REV,
    item.sku AS sku 
  FROM `gcs.rev` t,
  UNNEST(t.rev_info.purchase.virtual_items.items) item
)
WHERE currency = 'USD'
GROUP BY 1, 2, 3   

因此,所有 sku 将显示为给定 player_id 的列表,以及金额和货币

根据 Elliott 的评论/建议添加

#standardSQL
SELECT
  rev_info.user.id AS player_id,
  rev_info.purchase.total.currency AS currency,
  rev_info.purchase.total.amount AS REV,
  (SELECT STRING_AGG(item.sku) 
     FROM UNNEST(t.rev_info.purchase.virtual_items.items) item
  ) AS SKUs 
FROM `gcs.rev` t,
WHERE currency = 'USD'

【讨论】:

或者ARRAY(SELECT sku FROM UNNEST(t.rev_info.purchase.virtual_items.items)) AS sku 来避免聚合(您也可以使用STRING_AGG)。 完全同意。如果它是我的代码 - 我很可能会使用 (SELECT STRING_AGG(item.sku) FROM UNNEST(...) item) AS SKUs 之类的东西,而没有 GROUP BY 和没有 SELECT * 等。但是我在这里学到的关于在过去两年中每天回答的问题通常是 OP在许多情况下,尝试“简化”/混淆他们的代码,将他们的预期但真正重要的部分“小”留在外面,但通常他们不会转换/改变查询的结构。所以在这种情况下 - SELECT * 对我来说有点可疑,所以我尽量不改变内部查询【参考方案2】:

如果您的目标是为每个 items 数组元素获取一行,那么您可以在表和 rev_info.purchase.virtual_items.items 之间使用逗号(连接)运算符。例如,

SELECT *
FROM (
  SELECT
    rev_info.user.id as player_id,
    rev_info.purchase.total.currency as currency,
    rev_info.purchase.total.amount as REV,
    item.sku as sku 
  FROM `gcs.rev` t,
    t.rev_info.purchase.virtual_items.items item
)
WHERE currency = 'USD'

【讨论】:

谢谢,确实有效!但是,我很困惑为什么 SKU 是必要的,而不是 rev 或货币。特别是,我不明白为什么该标准显然正在执行的自动展平不直接执行此操作。 只有sku 才需要,因为包含它的字段 (items) 是一个数组。对于currencyamount等其他字段路径,路径上没有数组。使用标准 SQL 时,没有“自动展平”;你必须明确地表达你的意图(比如在这种情况下使用逗号)。

以上是关于无法使用 google bigquery(标准)取消嵌套某些字段的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery 中用于 Google Analytics 数据的标准 SQL 还是旧版 SQL?

BigQuery:如何在 C# 中启用标准 SQL

无法将数据插入现有 BigQuery 表?

Google 标准 SQL UDF - 写入 BigQuery

Google BigQuery 中的 TIMESTAMP 和标准 SQL

从 Google BigQuery 标准 SQL 中的数组生成随机值