在 BigQuery 中汇总来自 Analytics 查询的点击和会话数据

Posted

技术标签:

【中文标题】在 BigQuery 中汇总来自 Analytics 查询的点击和会话数据【英文标题】:Aggregate hits and sessions data from Analytics query in BigQuery 【发布时间】:2016-11-24 09:09:00 【问题描述】:

在 Google Analytics BigQuery 中,以下查询尝试在 sessionshits 级别聚合信息

SELECT
  visitId,
  trafficSource.source as source,
  trafficSource.medium as medium,
  device.browser as browser,
  min(hits.hour) as firstHitHour,
  boolean(count(hits.eventInfo.eventCategory = "SomeValue")) as hasSomeValue
FROM
  [my-table.ga_sessions_20150216]
GROUP BY
  visitId, source, medium, browser;

boolean(count(hits.eventInfo.eventCategory = "SomeValue")) as hasSomeValue 行应为true,如果在一行会话的所有点击中,至少有一个点击的hits.eventInfo.eventCategory 等于SomeValue

预期结果如下:

sessionId   source         medium      browser      firstHitHour     hasSomeValue
--------------------------------------------------------------------------------------
12318       google         cpc         firefox      12               true
13317       google         organic     safari       14               null
13551       bing           organic     firefox      14               true
13610       orange         display     chrome       14               true
14381       ***  referral    safari       15               false
14422       google         organic     chrome       15               true

但是,上面提到的那行似乎不起作用。即使我输入了一些愚蠢的值,例如hits.eventInfo.eventCategory = "Blablablabla",它仍然会为某些行输出true(而显然没有命中具有这个愚蠢的值)。

实际上,指令 count(hits.eventInfo.eventCategory = "Blablablabla") - 没有 boolean() 会返回看似随机的结果(与实际计数没有任何共同点)。

这条线应该是什么来触发正确的输出?

【问题讨论】:

【参考方案1】:

使用standard SQL 会更轻松。要检查 hits 中的值是否存在,请在其上使用 EXISTS 子句。例如,

SELECT
  visitId,
  trafficSource.source as source,
  trafficSource.medium as medium,
  device.browser as browser,
  (SELECT MIN(hour) FROM UNNEST(hits)) as firstHitHour,
  EXISTS (SELECT 1 FROM UNNEST(hits) WHERE eventInfo.eventCategory = "SomeValue") as hasSomeValue
FROM
  `my-table.ga_sessions_20150216`
GROUP BY
  visitId, source, medium, browser;

另请参阅migrating from legacy to standard SQL 上的指南。

如果您确实想坚持使用旧版 SQL,则需要将 WITHIN RECORD 与超过 hits 的计数结合使用。

【讨论】:

谢谢 - 我没有意识到我必须取消选中 Legacy SQL 框 - 现在我有来自 UNNEST(hits)UNNEST expression references column hits which is neither grouped nor aggregated at 错误 查看相关问题 - ***.com/questions/40792981/…【参考方案2】:

首先,使用boolean(count(hits.eventInfo.eventCategory = "SomeValue")) 的问题在于,如果 hits.eventInfo.eventCategory 有任何非 NULL 值(“SomeValue”或其他不同的值),它将返回true,并且仅在以下情况下才会返回false hits.eventInfo.eventCategory 的所有值都为空。但这并不是一个意外的结果:

    使用hits.eventInfo.eventCategory = "SomeValue",BQ 根据预期的条件将truefalse 分配给每个具有非NULL 值的命中,如果该命中具有null 值,则分配null。 但是,由于count返回函数范围内非NULL值的总数”,使用count(hits.eventInfo.eventCategory = "SomeValue")(按visitId分组)BQ返回@的聚合个数987654331@ AND false 之前获得,并且仅在给定 visitId 的所有命中都是 null 时返回 0。换句话说,它计算所有非空值,而不仅仅是那些满足条件的值,所以你的查询的问题就在这里。 boolean(...) 按预期工作:如果最后一个表达式不为 0 且不为 NULL,则返回 true,如果为 0,则返回 false,如果为 NULL,则返回 NULL(您不会获得任何 null)。

其次,正如您在上一条评论中所说,您可以使用some() 代替boolean(count()),但请注意,使用它您不会获得任何null 结果,正如您最初在提供的示例中想要的那样。如果至少有一个 hits.eventInfo.eventCategory 等于“SomeValue”,您将获得true,否则获得false。如果这对你来说没问题,我认为这是最好的选择。

但是,如果您想在会话的所有命中都为空 hits.eventInfo.eventCategory 时获得null,您可以使用:

SELECT
      visitId,
      trafficSource.source as source,
      trafficSource.medium as medium,
      device.browser as browser,
      min(hits.hour) as firstHitHour,
      boolean(MAX(              
               CASE WHEN hits.eventInfo.eventCategory = "SomeValue" THEN 1
                    WHEN hits.eventInfo.eventCategory != "SomeValue" THEN 0
                    ELSE null END
             )
         ) as hasSomeValue
FROM
  [my-table.ga_sessions_20150216]
GROUP BY
   visitId, source, medium, browser

首先,对于每个命中,如果满足条件,则分配 1,如果不满足,则分配 0,如果值为 null,则分配 null。其次,通过询问max(),如果至少有一个“SomeValue”,我们将得到 1,如果有非空值但它们都不同于“SomeValue”,我们将得到 0,如果所有命中都有空值hits.eventInfo.eventCategory 的空值。最后,我们使用boolean() 来得到truefalsenull,这取决于每种情况。

【讨论】:

【参考方案3】:

我找到了一种输出所需结果的方法,即使用some() 而不是boolean(count())

SELECT
  visitId,
  trafficSource.source as source,
  trafficSource.medium as medium,
  device.browser as browser,
  min(hits.hour) as firstHitHour,
  some(hits.eventInfo.eventCategory = "SomeValue") as hasSomeValue
FROM
  [my-table.ga_sessions_20150216]
GROUP BY
  visitId, source, medium, browser;

不过,我不太确定为什么 boolean(count()) 会触发意外结果。

【讨论】:

【参考方案4】:

下面试试

#standardSQL
SELECT
  visitId, source, medium, browser,
  MIN(hour) AS firstHitHour,
  LOGICAL_OR(hasValue) AS hasValue
FROM (
  SELECT
    visitId,
    trafficSource.source AS source,
    trafficSource.medium AS medium,
    device.browser AS browser,
    h.hour AS hour,
    EXISTS(SELECT 1 FROM UNNEST(hits) WHERE eventInfo.eventCategory = "SomeValue") AS hasValue
  FROM
   `my-table.ga_sessions_20161122`, UNNEST(hits) AS h
)
GROUP BY
visitId, source, medium, browser;

【讨论】:

以上是关于在 BigQuery 中汇总来自 Analytics 查询的点击和会话数据的主要内容,如果未能解决你的问题,请参考以下文章

在 AdWords 数据传输到 BigQuery 后查看 MCC 帐户的汇总数据

如何在bigquery中按月/年汇总

如何从未嵌套的数据(BigQuery 中的 Google Analytics 数据)返回正确的汇总总数

来自 Firebase 的数据未显示在 BigQuery/Data Studio 中

使用来自 Bigquery 的新数据更新 Data Studio

学习Oracle分析函数(Analytic Functions)