查询“记录”中的特定值

Posted

技术标签:

【中文标题】查询“记录”中的特定值【英文标题】:Querying specific values within a "RECORD" 【发布时间】:2020-12-23 08:19:52 【问题描述】:

我最近一直在尝试直接查询我们的 Firebase Analytics 数据,因为 Firebase 仪表板只有一些非常基本的数据查看功能。

看起来我们可以直接在 BigQuery 中查询数据,但是 BigQuery 使用的数据库类型似乎是基于列的存储,并且具有与 mysql 等传统数据库不同的数据类型。

所以我最终完成了以下任务:

我曾尝试阅读 BigQuery 官方文档中的一些文档,例如这里:

https://cloud.google.com/bigquery/docs/reference/standard-sql/arrays

但它似乎是关于数组的,我不太了解文档,并且在 BigQuery 仪表板中它说这些列实际上不是一个数组,它们的类型是“记录”:

..我也没有在网上找到太多信息。

所以尝试仍然查询这个,因为我真的不知道该怎么做,我只是尝试了一些可能会让你们看起来很愚蠢的事情哈哈哈:

SELECT *
FROM `diningcity-2ad82.analytics_171798853.events_20201222`
WHERE event_params.string_value.screen_name = "Deal details"
LIMIT 1000;

所以我尝试使用“。”作为一种告诉 BigQuery“首先进入 event_params,然后进入 string_value 然后进入 screen_name,检查最终值”的方式。

但 BigQuery 不喜欢它:

Cannot access field string_value on a value with type ARRAY<STRUCT<key STRING, value STRUCT<string_value STRING, int_value INT64, float_value FLOAT64, ...>>> at [3:20]

那么谁能帮我找出我做错了什么以及正确的方法是什么?

作为参考,我也尝试过阅读本教程,但也没有真正理解????????:

https://www.simba.com/products/BigQuery/doc/JDBC_InstallGuide/content/jdbc/bq/features/records.htm

【问题讨论】:

【参考方案1】:

BigQuery 表格式的含义是:

event_params 是一个结构数组——这就是“重复”的意思。 value 是该结构中的一个结构。 string_value 是该数组中的一个字符串字段。

我不知道为什么 BigQuery 在表描述中使用“记录”,而在文档中的其他任何地方都使用“结构”。

要访问数组,请使用unnest。一种方法是在FROM 子句中。正如您所说的查询,这将是:

SELECT *
FROM `diningcity-2ad82.analytics_171798853.events_20201222` e CROSS JOIN
     UNNEST(e.event_params) ep 
WHERE v.screen_name = 'Deal details'
LIMIT 1000;

唯一的问题是screen_name 可能是“键”值而不是列/字段名称。所以,你真的想要:

SELECT *
FROM `diningcity-2ad82.analytics_171798853.events_20201222` e CROSS JOIN
     UNNEST(e.event_params) ep 
WHERE ep.key = 'screen_name' AND
      ep.value.string_value = 'Deal details'
LIMIT 1000;

如果不想要结果集中的所有参数,可以使用:

SELECT * EXCEPT (event_params)

您也可以在子查询中执行此操作:

SELECT *
FROM `diningcity-2ad82.analytics_171798853.events_20201222` e         
WHERE EXISTS (SELECT 1
              FROM UNNEST(e.event_params) ep 
              WHERE ep.key = 'screen_name' AND
                    ep.value.string_value = 'Deal details'
LIMIT 1000;

如果您不想在一行可能有多个匹配项时将行数加倍,这很方便。

【讨论】:

嗨,我检查了你的答案,让我感到困惑的一件事是,Kyrylo 在 BigQuery 中的答案与你的非常相似,但有一个关键区别:从diningcity-2ad82 中选择 *。 analytics_171798853.events_20201222 as e, unnest(e.event_params) as ep WHERE ep.key = 'screen_name' AND ep.value.string_value = 'Deal details';在您的解决方案中,您还 CROSS JOIN "ep.value" 而不是只有 event_params,请问有什么区别?有吗? 实际上,如果我尝试您的第二个代码 sn-p,我在 BigQuery 编辑器中的 CROSS JOIN UNNEST(ep.value) AS v 部分出现错误:UNNEST 中引用的值必须是数组。 UNNEST 在 [2:124] 包含 STRUCT 类型的表达式似乎 ep.value 部分不能是 UNNESTED 或其他 根据数据的定义,value是记录数组中的字符串数组。 BigQuery 似乎不同意你的观点??? @FlorianMonfort 。 . .我误读了数据结构并适当地更新了答案。【参考方案2】:

我尝试重新创建您在下面查询的 WITH 子句中拥有的数据。为了访问数组元素(重复),你必须UNNEST他们:

with data as (
select array<struct<value struct<string_value STRING, int_value INT64>, key STRING>>[struct(struct('1', 1), 'key1'), struct(struct('2', 2), 'key2')] as event_params
)
select unnested_array.value.string_value, unnested_array.value.int_value 
from data, unnest(data.event_params) as unnested_array;

您的event_params 字段实际上是STRUCTARRAY。它的类型为RECORD,其模式为REPEATED,它们是来自旧版SQL 的命名,它等于ARRAYSTRUCTs。您可以找到标准 SQL 和旧版 SQL 数据类型的比较here。

您可以在文档中查看查询嵌套字段here 的一些示例。

【讨论】:

我使用 WITH 子句来模拟您在diningcity-2ad82.analytics_171798853.events_20201222 中拥有的数据,仅作为查询数据的示例。您不必使用 WITH 子句,而是在 FROM 子句中使用 diningcity-2ad82.analytics_171798853.events_20201222 而不是 data,然后您将可以访问您查询的表中的所有列。重要的部分是使用UNNEST(data.event_params),在你的情况下应该是相似的。如果不明白请告诉我,以便我提供更好的答案 我试过:SELECT * FROM diningcity-2ad82.analytics_171798853.events_20201222, UNNEST(event_params) WHERE event_params.string_value.screen_name = "交易详情" LIMIT 1000;还是同样的错误,我不明白 请试试这个:从diningcity-2ad82.analytics_171798853.events_20201222 中选择 * 作为 e,unnest(e.event_params) 作为 ep WHERE ep.key = 'screen_name' AND ep.value.string_value = 'Deal details'; 我也不明白“WITH”是做什么的,我不明白我为什么需要这个?我想通过执行 SELECT * 来选择所有列,然后使用 WHERE 进行过滤 在documentation 中查找有关WITH 子句的更多信息。如果您使用我之前评论中的查询,则不再需要 WITH 子句。最初,我使用WITH 子句来模拟您的表的行为...

以上是关于查询“记录”中的特定值的主要内容,如果未能解决你的问题,请参考以下文章

ClearML 从记录的值中获取最大值

从Array1中的特定行值中减去Array2中的行值

如何将光标设置到 Internet Explorer 中文本 INPUT 字段的字符串值中的特定位置?

查询“记录”中的特定值

如何从 ColdFusion 查询循环中的返回值中检查空值

如何在Django中查询具有特定数量的外键关系并且在这些外键值中具有特定值的对象?