【问题标题】:Aggregate hits and sessions data from Analytics query in BigQuery在 BigQuery 中汇总来自 Analytics 查询的点击和会话数据
【发布时间】: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       stackoverflow  referral    safari       15               false
14422       google         organic     chrome       15               true

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

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

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

【问题讨论】:

    标签: google-analytics google-bigquery


    【解决方案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 错误
    【解决方案2】:

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

    1. 使用hits.eventInfo.eventCategory = "SomeValue",BQ 根据预期的条件将truefalse 分配给每个具有非NULL 值的命中,如果该命中具有null 值,则分配null
    2. 但是,由于count返回函数范围内非NULL值的总数”,使用count(hits.eventInfo.eventCategory = "SomeValue")(按visitId分组)BQ返回@的聚合个数987654331@ AND false 之前获得,并且仅在给定 visitId 的所有命中都是 null 时返回 0。换句话说,它计算所有非空值,而不仅仅是那些满足条件的值,所以你的查询的问题就在这里。
    3. 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;
        

        【讨论】:

          猜你喜欢
          • 2015-08-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-02-26
          • 2022-10-24
          • 1970-01-01
          • 1970-01-01
          • 2010-10-11
          相关资源
          最近更新 更多