Pro*_*ted 2 mysql sql usage-statistics
我想知道是否有人可以通过一些SQL帮助我,以返回两天或更长时间(让我们以7天为参考)返回登录到数据库表中的唯一身份用户的数量。
我的日志表在每行中都包含一个时间戳(ts)和user_id,代表该用户当时的活动。
以下查询从该日志返回每日活动用户或DAU:
SELECT FLOOR(ts / 86400) AS day, COUNT(DISTINCT user_id) AS dau
FROM log
GROUP BY day ORDER BY day ASC
Run Code Online (Sandbox Code Playgroud)
现在,让我们说我想向此单个查询添加(或至少以最有效的方式进行检索)每周活跃用户或7天期间记录的唯一身份用户总数。但是,我不想将时间浪费在不重叠的几周内。我需要每天计算当天和前6天中看到的不同的user_id。
例如:
day users wau
1 1,2 2
4 1,3 3
7 3,4,5 5
8 5 4 (user_id 2 lost from count)
15 2 2 (user_ids 1,3,4 lost from count)
Run Code Online (Sandbox Code Playgroud)
感谢您提供的任何帮助,如果需要进一步说明,请随时通过评论询问。
要获得“每周平均用户”计数(根据我对您的规范的了解...“每天,该天和前六天所看到的不同user_id的计数”),请按照以下内容进行查询可用于。(查询还会返回“每日平均用户”计数。
SELECT d.day
, COUNT(DISTINCT u.user_id) AS wau
, COUNT(DISTINCT IF(u.day=d.day,u.user_id,NULL)) AS dau
FROM ( SELECT FLOOR(k.ts/86400) AS `day`
FROM `log` k
GROUP BY `day`
) d
JOIN ( SELECT FLOOR(l.ts/86400) AS `day`
, l.user_id
FROM `log` l
GROUP BY `day`, l.user_id
) u
ON u.day <= d.day
AND u.day > d.day - 7
GROUP BY d.day
ORDER BY d.day
Run Code Online (Sandbox Code Playgroud)
(我尚未对此进行测试;但是稍后,如果需要任何更正,我将更新此语句。)
此查询将给定日期(来自行u
源)的用户列表与日志表(行d
源)中的一组日期连接在一起。注意连接谓词(ON子句)中出现的文字“ 7”,这就是使用户列表与之前6天“匹配”的原因。
请注意,例如,可以通过在SELECT列表中添加另一个表达式,将其扩展以获取过去3天的唯一用户数。
, COUNT(DISTINCT IF(u.day<=d.day AND u.day>d.day-3,u.user_id,NULL)) AS 3day
Run Code Online (Sandbox Code Playgroud)
字面量“ 7”可以增加到更大的范围。上面表达式中的文字3可以更改为任意天数...我们只需要确保已经有足够的前一天行(from d
)联接到from的每一行u
。
性能注释:由于内联视图(或派生表,如MySQL所称),此查询可能不会很快,因为必须将这些内联视图的结果集具体化为中间MyISAM表。
内联视图的别名u
可能不是最佳;直接加入日志表可能更快。我在考虑在给定的一天中获得唯一的用户列表,这就是内联视图中的查询使我得到的东西。对我来说,将发生的事情概念化就更容易了。我当时在想,如果您当天有数百个相同的用户输入,那么在加入其他日期之前,内联视图会淘汰掉一大堆重复项。最好在u
和d
内联视图中添加WHERE子句以限制返回的天数。(d
内联视图将需要在更早的6天内添加。)
另一方面,如果ts列是TIMESTAMP数据类型,我将更倾向于使用DATE(ts)
表达式来提取日期部分。但这将在结果集中返回DATE数据类型,而不是整数,该数据类型将与您指定的结果集不同。)
SELECT d.day
, COUNT(DISTINCT u.user_id) AS wau
, COUNT(DISTINCT IF(u.day=d.day,u.user_id,NULL)) AS dau
FROM ( SELECT DATE(k.ts) AS `day`
FROM `log` k
GROUP BY `day`
) d
JOIN ( SELECT DATE(l.ts) AS `day`
, l.user_id
FROM `log` l
GROUP BY `day`, l.user_id
) u
ON u.day <= d.day
AND u.day > DATE_ADD(d.day, INTERVAL -7 DAY)
GROUP BY d.day
ORDER BY d.day
Run Code Online (Sandbox Code Playgroud)