Google analytics Unnest和totals.timesite(BigQuery和谷歌分析数据)

Google analytics Unnest和totals.timesite(BigQuery和谷歌分析数据),google-analytics,google-bigquery,Google Analytics,Google Bigquery,我想计算一个网站的所有访问者的总现场时间(并将其除以3600,因为它在原始数据中存储为秒),然后我想将其分解为content_组和一个称为content_level的自定义变量 问题的产生是因为content_group和content_level都嵌套在数组中,而timeOnSite是一个totals.-存储的变量,如果在包含和取消测试的查询中使用,该变量会膨胀。(content_组是一个普通的hits.-嵌套变量,而content_级别嵌套在嵌套在hits中的customDimensions

我想计算一个网站的所有访问者的总现场时间(并将其除以3600,因为它在原始数据中存储为秒),然后我想将其分解为content_组和一个称为content_level的自定义变量

问题的产生是因为content_group和content_level都嵌套在数组中,而timeOnSite是一个totals.-存储的变量,如果在包含和取消测试的查询中使用,该变量会膨胀。(content_组是一个普通的hits.-嵌套变量,而content_级别嵌套在嵌套在hits中的customDimensions中(第二级嵌套变量) (威尔和托马斯C很好地解释了这个问题出现的原因,但我无法将他们的建议应用于totals.timesite指标)

(我使用子查询是因为我计划使用UNION_ALL从多个表中提取数据,但我省略了该语法,因为我认为它与问题无关。)

问题:

*是否可以对hits.和hits.customDimensions都进行“本地取消测试”,以便在查询中使用totals.timesite而不膨胀

*有没有可能像我在会话和会话2中所做的那样,在站点上为时间做一个变通


*这个问题还有第三个隐藏的解决方案吗?

我无法完全测试这个解决方案,但它似乎对我的数据集起作用:

SELECT
  DATE,
  COUNT(DISTINCT CONCAT(fv, CAST(v AS STRING))) sessions,
  AVG(tos) avg_time_on_site,
  content_group,
  content_level
FROM(
  SELECT   
   date AS date,   
   fullvisitorid fv,
   visitid v,
   ARRAY(SELECT DISTINCT contentGroup.contentGroup1 FROM UNNEST(hits)) AS content_group,   
   ARRAY(SELECT DISTINCT value FROM UNNEST(hits) AS hits, UNNEST(hits.customDimensions) AS custd WHERE index = 51) AS content_level,   
   totals.timeOnSite / 3600 AS tos 
  FROM `dataset_id.ga_sessions_20170101`
  WHERE totals.timeOnSite IS NOT NULL
  )
CROSS JOIN UNNEST(content_group) content_group
LEFT JOIN UNNEST(content_level) content_level
GROUP BY
  DATE, content_group, content_level
我试图做的是首先避免对整个数据集执行
UNNEST(hits)
操作。因此,在第一个
SELECT
语句中,
content\u group
content\u level
存储为数组

在接下来的
SELECT
中,我取消了这两个数组,并计算了总会话数和平均现场时间,同时对所需字段进行分组(我在这里使用了平均值,因为在处理现场时间时,这似乎更有意义,但如果需要求和,您可以将
AVG
更改为
SUM

在此查询中,您不会遇到重复
timesite
的问题,因为避免了外部
unest(点击)
。当
unest(内容组)
unest(内容级)时
发生时,这些数组中的每个值只与站点上对应的
时间关联一次,因此不会发生重复。

我这样回答自己的问题似乎有些奇怪,但堆栈溢出外部的联系人帮助我解决了这一问题,所以这实际上是他的答案,而不是我的答案

会话持续时间的问题可以通过使用窗口函数来解决(您可以在BigQuery文档中阅读有关窗口函数的更多信息:)

要使窗口函数正常工作,需要subselect中的前置分区和WHERE子句中的subsubselect


还提供了一种更精确的计算会话的方法。

此查询的输出与我尝试复制的GA中的报告不匹配。与GA相比,querys会话加倍,SUM(站点上的time)比GA大12倍(计算SUM time比计算AVG time更容易,但您是对的,AVG time更有用!)明天我会再尝试一次,现在已经很晚了,我可能还没想清楚。你能确认你的GA报告中应用的过滤器与此查询中应用的过滤器相同吗?事实上,在上面的查询中找不到任何错误。再试一次,得到了相同的不匹配。也检查了过滤器,它们只过滤掉内部的流量和垃圾邮件域(例如afora.ru、akuhni.by等)。当我在没有自定义维度的情况下运行查询时(也就是说,没有任何不可测试的维度),结果的总和是正确的,所以对我来说,过滤器会干扰我的感觉有点奇怪(但我还是个新手,所以我可能是错的!)
SELECT
  DATE,
  COUNT(DISTINCT CONCAT(fv, CAST(v AS STRING))) sessions,
  AVG(tos) avg_time_on_site,
  content_group,
  content_level
FROM(
  SELECT   
   date AS date,   
   fullvisitorid fv,
   visitid v,
   ARRAY(SELECT DISTINCT contentGroup.contentGroup1 FROM UNNEST(hits)) AS content_group,   
   ARRAY(SELECT DISTINCT value FROM UNNEST(hits) AS hits, UNNEST(hits.customDimensions) AS custd WHERE index = 51) AS content_level,   
   totals.timeOnSite / 3600 AS tos 
  FROM `dataset_id.ga_sessions_20170101`
  WHERE totals.timeOnSite IS NOT NULL
  )
CROSS JOIN UNNEST(content_group) content_group
LEFT JOIN UNNEST(content_level) content_level
GROUP BY
  DATE, content_group, content_level
#StandardSQL
SELECT   
 iso_date,   
 content_group,   
 content_level,  
 COUNT(DISTINCT SessionId) AS sessions, 
 SUM(session_duration) AS session_duration 
FROM (   
     SELECT   
       date AS iso_date,   
       hits.contentGroup.contentGroup1 AS content_group,   
       (SELECT MAX(IF(index=51, value, NULL)) FROM UNNEST(hits.customDimensions)) AS content_level,  
       CONCAT(CAST(fullVisitorId AS STRING), CAST(visitId AS STRING)) AS SessionId, 
       (LEAD(hits.time, 1) OVER (PARTITION BY fullVisitorId, visitId ORDER BY hits.time ASC) - hits.time) / 3600000 AS session_duration 
     FROM `projectname.123456789.ga_sessions_20170101`,   
       unnest(hits) AS hits
     WHERE _TABLE_SUFFIX BETWEEN "20170101" AND "20170131" 
       AND (SELECT 
              MAX(IF(index=51, value, NULL)) 
            FROM 
              UNNEST(hits.customDimensions) 
            WHERE 
              value IN ("web", "phone", "tablet")
            ) IS NOT NULL 
     GROUP BY   
       iso_date, content_group, content_level
     ORDER BY 
       iso_date, content_group, content_level
    )   
GROUP BY iso_date, content_group, content_level
ORDER BY iso_date, content_group, content_level