处理 BigQuery 中未嵌套记录导致的重复行的最佳做法?
Posted
技术标签:
【中文标题】处理 BigQuery 中未嵌套记录导致的重复行的最佳做法?【英文标题】:Best practices for dealing with duplicate rows caused by unnested records in BigQuery? 【发布时间】:2020-09-18 13:06:30 【问题描述】:处理来自 Facebook 的数据往往涉及处理记录,在我的例子中,所有“辣”数据都在其中。但是,有一个缺点,即大量重复行,如果处理不当,可能会导致过度报告和/或数据差异。
以下是一个用例,当它与我的主要数据(来自不涉及任何取消嵌套的表)结合时,最终数字会略有差异。
使用的技术 - Facebook 数据 -> Stitch -> BigQuery -> dbt -> Google Data Studio
我通常会创建单独的模型,在其中取消嵌套记录、转换数据,然后将其加入到我的其余模型中。这方面的一个示例是从 ads_insights 的操作记录中获取所有网站购买转化。不过这里有区别:
查询:
SELECT count(*) AS row_count
FROM ads_insights
结果:row_count - 316
查询:
SELECT count(*) AS row_count
FROM ads_insights,
UNNEST(actions) AS actions
结果:row_count - 5612
取消嵌套后,我会使用行数据为每次转化创建列,如下所示:
CASE WHEN value.action_type = 'offsite_conversion.fb_pixel_purchase' THEN COALESCE(value._28d_click, 0) + COALESCE(value._1d_view, 0) ELSE 0 END AS website_purchase
最后,我会将这个模型加入到我的其他模型中。唯一的问题是,这 5600 行在与其余行连接时会导致轻微差异,并且由于我已经使用行数据创建列,我不再关心未嵌套的记录数据,我可以返回到我原来的 316 行。唯一的问题是如何?有哪些技术可以帮助我清理模型?
解决方案: 尽管在某些时候我会像 dylanbaker 在他的回答中建议的那样聚合和分组查询中的所有字段,但差异仍然存在,在深入研究我的数据后,我发现未嵌套的查询将返回 279 行,而嵌套的将返回 314。这将我的注意力集中在取消嵌套查询上,它将删除 35 行,而这 35 行恰好为空。在进行了一些谷歌搜索后,我发现了这个 *** article,它建议使用 LEFT JOIN UNNEST 来保留所有具有空记录值的行,而不是 CROSS JOIN UNNEST 来删除它们。
【问题讨论】:
【参考方案1】:您通常希望在此处进行“枢转”。您已经完成了大部分工作,您只需要按相关列进行汇总和分组,以便将其恢复到您最初拥有和想要的粒度。
我相信你会想要这样的东西:
select
ads_insights.some_column,
ads_insights.some_other_column,
sum(case
when value.action_type = 'offsite_conversion.fb_pixel_purchase'
then coalesce(value._28d_click, 0) + coalesce(value._1d_view, 0)
else 0
end) AS website_purchase
from ads_insights,
unnest(actions) as actions
group by 1,2
初始列可以是您想要的原始表中的任何内容。 'sum case whens' 是对未嵌套的数据进行透视和聚合。
【讨论】:
这也是我的想法,但是对非聚合字段进行分组并不会减少它,因为取消嵌套已经对其余数据造成了严重破坏(例如像支出这样的列)我会将您的代码用作称为“操作”的 CTE,我将在其中进行数据透视,另一个称为“见解”的 CTE 将在其中获得“some_column”和“some_other_column”的 ad_spend,而无需进行任何取消嵌套。第一个 CTE (CTE1) 将返回 279 行,而第二个 CTE (CTE2) 314。当我离开 join CTE1 和 CTE2 时,我最终得到 279。当我 FULL JOIN 时,我最终得到 314 行但 35 col1 和col2 为空。 好的,我认为丢失的 35 条记录没有任何操作,因此当我取消嵌套(操作)时,它们会从表中删除,因为它们为空。在做了一个快速的谷歌搜索后,我发现这篇 *** 文章建议不要使用 CROSS JOIN UNNEST(record),而是使用 LEFT JOIN UNNEST(record),它也将保留所有空值。事实证明这是拼图的最后一块!文章链接:***.com/questions/44918108/… 关于您的第一条评论,为什么按支出分组不起作用?所有相关操作的花费不都一样吗? 您完全正确,我也可以按 ad_spend 分组并跳过 2 个额外的 CTE!【参考方案2】:您实际上可以在 select 语句中使用 unnests 来做一些魔术
这对你有用吗?
SELECT
some_column,
(SELECT coalesce(_28d_click, 0) + coalesce(_1d_view, 0) from unnest(actions) WHERE action_type = "offsite_conversion.fb_pixel_purchase") AS website_purchase
FROM ads_insights
【讨论】:
当我第一次了解标量子查询时,我真的很兴奋,但我的兴奋是短暂的,因为 BigQuery 不允许我一次运行超过 6 到 7 个,就我而言,我们是谈论同时旋转数十个字段,所以我回到了最初的解决方案。只需将 CROSS JOIN UNNEST 更改为 LEFT JOIN UNNEST 以保留所有空值并避免数据差异。以上是关于处理 BigQuery 中未嵌套记录导致的重复行的最佳做法?的主要内容,如果未能解决你的问题,请参考以下文章
如何查询非规范化 BigQuery 表以输出嵌套和重复的字段