从BigQuery中的Analytics查询汇总匹配和会话数据

时间:2016-11-24 09:09:01

标签: google-analytics google-bigquery

在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。< / p>

预期结果如下:

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()会返回看似随机的结果(与实际计数没有任何共同点)。

这条线应该触发正确的输出?

4 个答案:

答案 0 :(得分: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 RECORDhits上的计数结合使用。

答案 1 :(得分:1)

首先,使用boolean(count(hits.eventInfo.eventCategory = "SomeValue"))的问题是,如果hits.eventInfo.eventCategory具有任何非NULL值(&#34; SomeValue&#34;或其他不同),它将返回true当hits.eventInfo.eventCategory的所有值都为null时,它只返回false。但这不是一个意想不到的结果:

  1. 使用hits.eventInfo.eventCategory = "SomeValue",BQ根据预期条件为每个匹配分配truefalse非空值,null如果该匹配具有null {1}}值。
  2. 但是,由于count&#34; 返回函数范围内非NULL值的总数&#34;,使用count(hits.eventInfo.eventCategory = "SomeValue")(分组) by visitId)BQ返回之前获得的true AND false的汇总数,如果给定的visitId的所有匹配均为null,则仅返回0。换句话说,它会计算所有非空值,而不仅仅是那些满足条件的值,因此您的查询问题就在这里。
  3. boolean(...)按预期工作:如果最后一个表达式不为0则返回true,如果为0,则返回false;如果为0,则返回NULL(如果它不是null,则返回NULL)。
  4. 其次,正如您在上次评论中所说,您可以使用some()代替boolean(count()),但请注意使用它时您不会获得任何null结果,因为您最初想要在提供的示例中。如果至少有一个hits.eventInfo.eventCategory等于&#34; SomeValue&#34;你将获得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(),如果存在至少一个&#34; SomeValue&#34;我们将获得1,如果存在非空值但是所有这些都与&不同,则为0 #34; SomeValue&#34;,如果所有匹配都具有hits.eventInfo.eventCategory的空值,则为null。最后,我们使用boolean()来获取truefalsenull,具体视具体情况而定。

答案 2 :(得分:0)

我找到了一种输出所需结果的方法,使用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())会触发意外结果。

答案 3 :(得分:0)

尝试以下

#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;