如何简化和扩展 Firebase 数据库上的 BigQuery 子过滤 event_params
Posted
技术标签:
【中文标题】如何简化和扩展 Firebase 数据库上的 BigQuery 子过滤 event_params【英文标题】:How to simplify and expand BigQuery subfiltering event_params on firebase database 【发布时间】:2020-11-27 10:56:11 【问题描述】:我正在尝试进行 BigQuery 查询以从 firebase db 子表 event_params
中提取数据。
表 events_* 有一个事件列表,其中字段 event_params
是一个结构,其中包含key
、int_value
形式的表以及在这种情况下未使用的其他字段。
例如,1 个单个事件可能有一个 event_params 列表,如下所示:
key int_value
level 1
time 35
kills 10
我想按级别过滤事件列表,但从该事件中选择时间。我得到的解决方案是这样的:
select user_pseudo_id, x.value.int_value as time
from (
select user_pseudo_id, event_params
from `whatever.events_*`, unnest(event_params) as y
where event_name = 'level_complete' and y.key = 'level' and y.value.int_value = 1
), unnest(event_params) as x
where x.key = 'time'
它适用于这种情况,但我有一些关于如何改进和使其发展的问题:
有没有办法在一个查询中简化这一点? 如果我想获取时间字段和杀人字段怎么办? (我能想到的唯一解决方案是复制查询并连接两个结果,但如果我想提取大量字段怎么办?)。 是否可以通过创建类似函数的函数来简化这一点,该函数返回像Filter('level_complete', 'level', 1)
这样的结果表?
提前致谢!
【问题讨论】:
提供样本数据和预期结果 【参考方案1】:这个资源占用较少,因为它不执行聚合:
select *
from (
select
user_pseudo_id,
event_name,
(select int_value from unnest(event_params) where key = 'level') as level,
(select int_value from unnest(event_params) where key = 'time') as time,
(select int_value from unnest(event_params) where key = 'kills') as kills
from `whatever.events_*`
where event_name = 'level_complete'
)
where level = 1
【讨论】:
您能提供一个参考,说明子选择比 BQ 中的聚合便宜吗? 另外,公平的警告,如果一个键在任何行的event_params
中重复,整个查询将失败,Scalar subquery produced more than one element
嗨,完全同意。这不适合单行中有多个重复键的情况。资源消耗我通常在“执行详细信息”选项卡(“结果”旁边)中检查。
当您使用此类查询检查“执行详细信息”时,您是否看到子选择优于聚合?你的主张This one is less resource intensive because it does not perform aggregation
的证据在哪里?
当然,只需比较聚合和子选择的执行细节。例如,对于您的答案中的样本数据,子选择的“计算”总数较少。【参考方案2】:
透视数据:
# start with some sample data
with data as (
select 1 as user_pseudo_id, 'level_complete' as event_name, [struct('level' as key, 1 as int_value), struct('time' as key, 35 as int_value), struct('kills' as key, 10 as int_value)] as event_params
UNION ALL
select 2 as user_pseudo_id, 'level_complete' as event_name, [struct('level' as key, 4 as int_value), struct('time' as key, 10 as int_value), struct('kills' as key, 1 as int_value)] as event_params
UNION ALL
select 3 as user_pseudo_id, 'level_complete' as event_name, [struct('level' as key, 6 as int_value), struct('time' as key, 30 as int_value), struct('kills' as key, 2 as int_value)] as event_params
UNION ALL
select 3 as user_pseudo_id, 'other_type' as event_name, [struct('bad' as key, 5 as int_value), struct('time' as key, 40 as int_value), struct('kills' as key, 3 as int_value)] as event_params
)
# This is the "code" part
select user_pseudo_id, event_name,
max(if(params.key = 'level', int_value, null)) level,
max(if(params.key = 'time', int_value, null)) time,
max(if(params.key = 'kills', int_value, null)) kills,
array_agg(distinct if(params.key in ('level','time','kills'), null, params.key) ignore nulls) as unexpected_keys
from data
CROSS JOIN unnest(event_params) as params
group by user_pseudo_id, event_name
或者,如果您更喜欢以这种格式创建转换表,请尝试fhoffa.x.pivot()
我一直将这种技术用于查询key
的所有唯一值的python 程序,然后使用适当的动态列创建VIEW
。如果您的值是静态的,那么手写 SQL 会更简单。
【讨论】:
以上是关于如何简化和扩展 Firebase 数据库上的 BigQuery 子过滤 event_params的主要内容,如果未能解决你的问题,请参考以下文章
Firebase 可扩展性:整个数据集上的观察者与多个观察者
如何使用带有平台、steam_id、event_name 过滤器的 bigquery 在 power bi 中编写查询以查找过去 28 天的 firebase 事件详细信息?