7 天用户计数:Big-Query 自加入以获取日期范围和计数?

Posted

技术标签:

【中文标题】7 天用户计数:Big-Query 自加入以获取日期范围和计数?【英文标题】:7-day user count: Big-Query self-join to get date range and count? 【发布时间】:2019-06-17 11:57:11 【问题描述】:

我的 Google Firebase 事件数据已集成到 BigQuery,我正在尝试从此处获取 Firebase 自动为我提供的信息之一:1 天、7 天、28 天用户计数。

1 天计数非常简单

SELECT
  "1-day" as period,
  events.event_date,
  count(distinct events.user_pseudo_id) as uid
FROM
  `your_path.events_*` as events
WHERE events.event_name = "session_start"
group by events.event_date

有一个整洁的结果,如

period   event_date  uid
1-day    20190609    5
1-day    20190610    7
1-day    20190611    5
1-day    20190612    7
1-day    20190613    37
1-day    20190614    73
1-day    20190615    52
1-day    20190616    36

但对我而言,当我尝试统计过去 7 天中每天拥有的唯一身份用户数时,事情变得复杂了 从上面的查询中,我知道我的第 20190616 天的目标值为 142,通过过滤 7 天并按条件删除组。

我尝试的解决方案是直接自加入(以及没有改变结果的变体)

SELECT
  "7-day" as period,
  events.event_date,
  count(distinct user_events.user_pseudo_id) as uid
FROM
  `your_path.events_*` as events,
  `your_path.events_*` as user_events
WHERE user_events.event_name = "session_start"
  and PARSE_DATE("%Y%m%d", events.event_date) between DATE_SUB(PARSE_DATE("%Y%m%d", user_events.event_date), INTERVAL 7 DAY) and PARSE_DATE("%Y%m%d", user_events.event_date) #one day in the first table should correspond to 7 days worth of events in the second
  and events.event_date = "20190616" #fixed date to check
group by events.event_date

现在,我知道我几乎没有设置任何连接条件,但如果有的话,我希望会产生交叉连接和巨大的结果。相反,这种方式的计数是 70,这比预期的要低很多。此外,我可以设置 INTERVAL 2 DAY 并且结果不会改变。

我这里显然做错了什么,但我也觉得我做的方式很初级,一定有更聪明的方法来完成。

我已经检查了Calculating a current day 7 day active user with BigQuery?,但是这里的显式交叉连接是使用 event_dim 我不确定的定义


按照评论的建议,检查了Rolling 90 days active users in BigQuery, improving preformance (DAU/MAU/WAU) 提供的解决方案。 该解决方案起初看起来很合理,但最近出现了一些问题。这是使用 COUNT(DISTINCT) 的查询,我适应了我的情况

SELECT DATE_SUB(event_date, INTERVAL i DAY) date_grp
 , COUNT(DISTINCT user_pseudo_id) unique_90_day_users
 , COUNT(DISTINCT IF(i<29,user_pseudo_id,null)) unique_28_day_users
 , COUNT(DISTINCT IF(i<8,user_pseudo_id,null)) unique_7_day_users
 , COUNT(DISTINCT IF(i<2,user_pseudo_id,null)) unique_1_day_users
FROM (
  SELECT PARSE_DATE("%Y%m%d",event_date) as event_date, user_pseudo_id
  FROM `your_path_here.events_*`
  WHERE EXTRACT(YEAR FROM PARSE_DATE("%Y%m%d",event_date))=2019
  GROUP BY 1, 2
), UNNEST(GENERATE_ARRAY(1, 90)) i
GROUP BY 1
ORDER BY date_grp

这是最近几天的结果(考虑数据从 5 月 23 日开始),您可以看出结果是错误的

row_num   date_grp     90-day  28-day  7-day   1-day
114       2019-06-16   273     273     273     210
115       2019-06-17   78      78      78      78

所以在最后一天,90 天、28 天、7 天的计数仅考虑同一天,而不是之前的所有天。 如果 6 月 16 日的 1 天更高,那么 6 月 17 日的 90 天计数不可能是 78。

【问题讨论】:

您有可以使用的日历\日期表吗?如果是这样,您可以跳过 CROSS JOIN。 你检查了吗***.com/a/49866033/132438 我尝试了 Felipe 链接的解决方案。不幸的是,我不能满足某些条件:不能确定这些天不会有空档,并且 HLL_COUNT 没有显示任何结果。将尽快发布编辑 【参考方案1】:

这是对我同样问题的AN回答。 我的方法很简陋,因为我对 BQ 快捷键和一些高级功能不是很熟悉,但结果仍然是正确的。 我希望其他人能够集成更好的查询。

#standardSQL
WITH dates AS (
  SELECT i as event_date
  FROM UNNEST(GENERATE_DATE_ARRAY('2019-05-24', CURRENT_DATE(), INTERVAL 1 DAY)) i
)
, ptd_dates as (
  SELECT DISTINCT "90-day" as day_category, FORMAT_DATE("%Y%m%d",event_date) AS event_date, FORMAT_DATE("%Y%m%d",DATE_SUB(event_date, INTERVAL i-1 DAY)) as ptd_date
  FROM dates,
    UNNEST(GENERATE_ARRAY(1, 90)) i
  UNION ALL
  SELECT distinct "28-day" as day_category, FORMAT_DATE("%Y%m%d",event_date) AS event_date, FORMAT_DATE("%Y%m%d",DATE_SUB(event_date, INTERVAL i-1 DAY)) as ptd_date
  FROM dates,
    UNNEST(GENERATE_ARRAY(1, 29)) i
  UNION ALL
  SELECT distinct "7-day" as day_category, FORMAT_DATE("%Y%m%d",event_date) AS event_date, FORMAT_DATE("%Y%m%d",DATE_SUB(event_date, INTERVAL i-1 DAY)) as ptd_date
  FROM dates,
    UNNEST(GENERATE_ARRAY(1, 7)) i
  UNION ALL
  SELECT distinct "1-day" as day_category, FORMAT_DATE("%Y%m%d",event_date) AS event_date, FORMAT_DATE("%Y%m%d",event_date) as ptd_date
  FROM dates
)


SELECT event_date,
  sum(IF(day_category="90-day",unique_ptd_users,null)) as count_90_day ,
  sum(IF(day_category="28-day",unique_ptd_users,null)) as count_28_day,
  sum(IF(day_category="7-day",unique_ptd_users,null)) as count_7_day,
  sum(IF(day_category="1-day",unique_ptd_users,null)) as count_1_day
from (
SELECT ptd_dates.day_category
  , ptd_dates.event_date
  , COUNT(DISTINCT user_pseudo_id) unique_ptd_users
FROM ptd_dates,
  `your_path_here.events_*` events,
  unnest(events.event_params) e_params
WHERE ptd_dates.ptd_date = events.event_date
GROUP BY ptd_dates.day_category
  , ptd_dates.event_date)
group by event_date
order by 1,2,3

根据 ECris 的建议,我首先定义了一个要使用的日历表:它包含 4 类 PTD(从周期到日期)。每个都是从基本元素生成的:这应该是线性扩展的,因为它不查询事件数据集,因此没有间隙。

然后使用事件进行连接,其中连接条件显示我如何在每个日期计算该期间所有相关日期的不同用户。

结果是正确的。

【讨论】:

以上是关于7 天用户计数:Big-Query 自加入以获取日期范围和计数?的主要内容,如果未能解决你的问题,请参考以下文章

获取过去 7 天以来的行数

倒计时7天!AIRIOT新品发布会,6月6日北京见。

Beta 冲刺 (1/7)

Beta 冲刺 (1/7)

Beta 冲刺 (1/7)

Beta 冲刺 (1/7)