使用 Flatten 从包含多个嵌套变量的 bigquery 表中选择 where var1 (non-repeated) = "abc"?
Posted
技术标签:
【中文标题】使用 Flatten 从包含多个嵌套变量的 bigquery 表中选择 where var1 (non-repeated) = "abc"?【英文标题】:Using Flatten to select where var1 (non-repeated) = "abc" from a bigquery table which contains multiple nested variables? 【发布时间】:2017-06-20 22:51:03 【问题描述】:我对 BigQuery 还很陌生(使用它的第 3 天,没有经过培训),我只是想了解嵌套字段等。
我查看了以下资源并使用了 google bigquery 文档链接上的 peopledata 示例
https://cloud.google.com/bigquery/docs/data
https://chartio.com/resources/tutorials/how-to-flatten-data-using-google-bigquerys-legacy-vs-standard-sql/
我想运行以下查询:
select *
from [dataset.tableid]
where fullname = 'John Doe'
如果我运行它,我会收到以下错误:
错误:无法同时输出多个独立重复的字段。找到 children_age 和 cityLived_place
通过阅读上述文章,这是不可能的,因为您需要展平结果,据我所知,这只是复制所有非重复变量,即
全名 |年龄 |性别 |孩子的名字 |儿童年龄
约翰·多伊 | 22 |男 |约翰 | 5
约翰·多伊 | 22 |男 |简 | 7
上面的一篇文章建议您仍然可以通过使用 bigquery 中的 flatten 函数来使用 where 语句:
select fullname,
age,
gender,
citiesLived.place
FROM (FLATTEN([dataset.tableId], children))
WHERE
(citiesLived.yearLived > 1995) AND
(children.age > 3)
GROUP BY fullName, age, gender, citiesLived.place
如果我将其更改为:
select *
FROM (FLATTEN([dataset.tableId], children))
WHERE fullname = 'John Doe'
然后这工作正常并给了我我需要的东西但是如果我改变这个:
select *
FROM (FLATTEN([dataset.tableId], citieslived))
WHERE fullname = 'John Doe'
然后我得到以下错误:
错误:无法同时输出多个独立重复的字段。找到 children_age 和 cityLived_yearsLived
有人可以解释为什么这会基于“Children”而不是“CitiesLived”进行展平,以及如何知道在使用具有多个嵌套变量的更复杂数据集进行展平时使用哪些变量?
提前谢谢你
【问题讨论】:
是否有理由尝试使用旧版 SQL 执行此操作?我建议改用标准 SQL,因为它使基于数组的转换更容易表达。 嗨,Elliott,感谢您的快速回复,抱歉,我什至不知道 bigquery 有两种 SQL 方言。让我看看这个以了解迁移以及我们为什么使用遗留语言。如果您对使用标准 SQL 有任何指示,请告诉我。谢谢 【参考方案1】:如果您运行此查询:
SELECT
*
FROM
(FLATTEN((FLATTEN(([project_id:dataset_id.table]), citiesLived.yearsLived)), citiesLived))
它会按预期变平。
当使用旧版 SQL 时,BQ 会尝试为您flatten automatically 结果。
我注意到的是,如果您尝试展平其中包含其他重复字段的重复字段,那么有时您可能会遇到这些错误(请注意,字段 citiesLived
和 citiesLived.yearsLived
都是重复的)。
因此,解决此问题的一种方法是强制对您要使用的所有重复字段进行展平操作(在我向您展示的示例中,我首先展平了 yearsLived,然后 citiesLived) 并且不依赖于旧版 SQL 提供的自动展平操作。
但我强烈建议并鼓励您按照 Elliot 在评论中的建议学习 BQ 的标准 SQL 版本。一开始它可能有一个更陡峭的学习曲线,但从长远来看它会完全得到回报(并且您不会有最终不得不将所有遗留查询迁移到标准的风险,就像我们在我们公司所做的那样)
【讨论】:
感谢您的建议 Will,我没有意识到 SQL 在 bigquery 中有两种方言。我将进一步研究迁移到标准 SQL。【参考方案2】:有人能解释一下为什么这会基于“儿童”而不是“城市生活”进行扁平化
再次检查该表的架构
Schema
-----------------------------------
|- kind: STRING
|- fullName: STRING (required)
|- age: INTEGER
|- gender: STRING
+- phoneNumber: RECORD
| |- areaCode: INTEGER
| |- number: INTEGER
+- children: RECORD (repeated)
| |- name: STRING
| |- gender: STRING
| |- age: INTEGER
+- citiesLived: RECORD (repeated)
| |- place: STRING
| +- yearsLived: INTEGER (repeated)
如您所见 - 当您将 children
重复记录展平时 - 唯一要输出的重复记录是 citiesLived
并且即使它内部还有另一个重复字段 - yearsLived
- 它们是 不独立 - 因此 BigQuery Legacy SQL 可以输出结果
现在,当您将 citiesLived
变平时 - 结果是两个重复的文件 - children
和 yearsLived
。这两个是独立的 - 因此 BigQuery Legacy SQL 无法输出这样的结果。
如何知道在包含多个嵌套变量的更复杂数据集的扁平化中使用哪些变量?
要使其工作 - 您应该添加另一个展平(例如)yearsLived
归档。像下面这样的
FROM (FLATTEN(FLATTEN([dataset.tableId], citieslived), yearsLived))
添加所有这些多个 FLATTEN 可能会变得很麻烦,因此使用 BigQuery 标准 SQL 确实是要走的路!
见Migrating from Legacy SQL 到BigQuery Standard SQL
【讨论】:
感谢您的快速回复米哈伊尔!我是否正确地说,如果有与您正在展平的字段相关的依赖字段,您必须指定并展平所有这些依赖字段?我不知道 bigquery 中有两种 SQL 方言。感谢您的提示! Legacy SQL 输出重复字段是没有问题的,如果它们是依赖的。你需要扁平化那些独立的。但是,从这里开始的最佳方式仍然是迁移到 BigQuery 标准 SQL。它有更好的处理记录的方法。看看 ARRAYs 有一个想法 - cloud.google.com/bigquery/docs/reference/standard-sql/arrays 感谢 Mikhail,我刚刚尝试使用标准 SQL 从我们的实时 bigquery 数据集中进行选择,但是我收到以下错误:错误:语法错误:意外的浮点文字“ 8286363。”在 [2:6]。我不确定您是否能够阐明此错误,但我猜这是因为我们已将数据集命名为“8286363”,而 bigquery 只能处理以字符开头的数据集? 您应该发布具有特定问题的新问题 - 这样我们才能回答。评论不允许有效回答,也不是真正的 SO 运作方式。它更多的是问答网站,而不是讨论论坛。所以发布新问题。同时,如果它回答了您当前的问题,请选择一个答案并接受它。希望这对你有意义:o) 同时 - 我认为你的猜测是正确的 - 你可以在这里查看更多信息 cloud.google.com/bigquery/docs/reference/standard-sql/lexical以上是关于使用 Flatten 从包含多个嵌套变量的 bigquery 表中选择 where var1 (non-repeated) = "abc"?的主要内容,如果未能解决你的问题,请参考以下文章
Python Flatten 用 Pandas 将嵌套字典 JSON 相乘