Unnest 和 totals.timeOnSite(BigQuery 和 Google Analytics 数据)
Posted
技术标签:
【中文标题】Unnest 和 totals.timeOnSite(BigQuery 和 Google Analytics 数据)【英文标题】:Unnest and totals.timeOnSite (BigQuery and Google Analytics data) 【发布时间】:2017-07-21 07:37:51 【问题描述】:我想计算网站所有访问者的总 timeOnSite(并将其除以 3600,因为它在原始数据中存储为秒),然后我想将其分解为 content_group 和一个名为的自定义变量内容级别。
出现问题是因为 content_group 和 content_level 都嵌套在数组中,而 timeOnSite 是一个总计存储的变量,如果在包含和取消嵌套的查询中使用时会膨胀。 (content_group 是一个普通的 hits.-nested 变量,而 content_level 嵌套在 customDimensions 中,该 customDimensions 嵌套在 hits 中(第二级嵌套变量) (Will 和 Thomas C 很好地解释了为什么这个问题会出现在这个问题 Google Analytics Metrics are inflated when extracting hit level data using BigQuery 中,但我无法将他们的建议应用于 totals.timeOnSite 指标)
#StandardSQL
SELECT
date,
content_group,
content_level,
SUM(sessions) AS sessions,
SUM(sessions2) AS sessions2,
SUM(time_on_site) AS time_on_site
FROM (
SELECT
date AS date,
hits.contentGroup.contentGroup1 AS content_group,
(SELECT MAX(IF(index=51, value, NULL)) FROM UNNEST(hits.customDimensions)) AS content_level,
SUM(totals.visits) AS sessions,
COUNT(DISTINCT CONCAT(cast(visitId AS STRING), fullVisitorId)) AS sessions2,
SUM(totals.timeOnSite)/3600 AS time_on_site
FROM `projectname.123456789.ga_sessions_20170101`,
unnest(hits) AS hits
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
(我使用子查询是因为我计划使用 UNION_ALL 从多个表中提取数据,但我省略了该语法,因为我认为它与问题无关。)
问题:
*是否可以对两个命中进行“本地取消嵌套”。和 hits.customDimensions 以便可以在我的查询中使用 totals.timeOnSite 而不会被夸大?
*是否可以像我在会话和会话2中所做的那样为现场时间制定解决方法?
*这个问题是否有第三种隐藏的解决方案?
【问题讨论】:
【参考方案1】:我无法完全测试这个,但它似乎对我的数据集起作用:
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_group
和 content_level
存储为 ARRAY。
在接下来的 SELECT
中,我取消了这两个 ARRAY 的嵌套,并在对所需字段进行分组时计算了总会话数和现场平均时间(我在这里使用了平均值,因为在处理现场时间,但如果您需要总和,您可以将AVG
更改为SUM
)。
您不会在此查询中遇到重复timeOnSite
的问题,因为避免了外部UNNEST(hits)
。当UNNEST(content_group)
和UNNEST(content_level)
发生时,这些ARRAY 中的每个值仅与其对应的time_on_site
关联一次,因此不会发生重复。
【讨论】:
此查询的输出与我尝试复制的 GA 中的报告不匹配。与 GA 相比,查询会话增加了三倍,SUM(time_on_site) 比 GA 大 12 倍(评估 SUM 时间比 AVG 时间更容易,但你说得对,AVG 时间更有用!)我明天再试一次,我现在已经很晚了,我可能没有想清楚。 您能否确认您的 GA 报告中应用的过滤器与此查询中应用的过滤器相同?因为在上面的查询中找不到任何错误。 又试了一次,结果还是一样。也检查了过滤器,它们只过滤掉内部流量和垃圾邮件域(例如 afora.ru、akuhni.by 等)。当我在没有自定义维度(即没有任何取消嵌套)的情况下运行查询时,总和结果是正确的,所以对我来说过滤器会干扰感觉有点奇怪(但我仍然是新手,所以我可能是错的! )【参考方案2】:我这样回答自己的问题可能看起来很奇怪,但是我在 Stack Overflow 之外的一位联系人帮助我解决了这个问题,所以这实际上是他的答案,而不是我的。
session_duration 的问题可以通过使用窗口函数来解决(您可以在 BigQuery 文档中阅读有关窗口函数的更多信息:https://cloud.google.com/bigquery/docs/reference/standard-sql/functions-and-operators#analytic-functions)
#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
子选择中的 LEAD - OVER - PARTITION 和 WHERE 子句中的子子选择都是窗口函数正常工作所必需的。
还提供了一种更准确的会话计算方法。
【讨论】:
以上是关于Unnest 和 totals.timeOnSite(BigQuery 和 Google Analytics 数据)的主要内容,如果未能解决你的问题,请参考以下文章
使用 Psycopg2 和 unnest 时的“未知”数据类型
tidytext:unnest_tokens 和 token = 'ngrams' 的问题
Google BigQuery:UNNEST 结构数组和未嵌套项作为结构