使用T-SQL滚动DAU,MAU

时间:2019-05-08 14:13:25

标签: sql sql-server

情况:

我有一个登录表,其中包含列email和login_time。我想计算每日登录时间(DAU)和滚动每月登录时间(MAU)。 DAU和MAU必须计算不同的用户。即,如果某人在过去30天内(MAU)登录了20次,则该人只会被计数一次。 DAU的逻辑相同。 MAU的范围是30天。

DAU:是通过每天使用不同的电子邮件登录名来计算的。

MAU:是通过连续30天使用不同的电子邮件登录名来计算的。

所需结果: 请参见下面的小提琴

Date         MAU     DAU     
2019-04-01   4       2  
2019-04-02   3       2  
2019-04-03   4       2   

计算DAU非常简单,但是要获得滚动的MAU,不确定如何做到。

小提琴:

create table #t1 (email varchar(max), login_time datetime)
insert into #t1 values 
('aa@gmail.com', '2019-03-15 00:00:00.000'),
('aa@gmail.com', '2019-04-01 00:00:00.000'),
('aa@gmail.com', '2019-04-02 00:00:00.000'),
('aa@gmail.com', '2019-04-03 00:00:00.000'),

('bb@gmail.com', '2019-03-19 00:00:00.000'),
('bb@gmail.com', '2019-04-01 00:00:00.000'),
('bb@gmail.com', '2019-04-02 00:00:00.000'),
('bb@gmail.com', '2019-04-02 00:00:00.000'),

('cc@gmail.com', '2019-03-02 00:00:00.000'),
('cc@gmail.com', '2019-04-03 00:00:00.000'),

('dd@gmail.com', '2019-03-06 00:00:00.000')

2 个答案:

答案 0 :(得分:1)

这是一种实现方式。

SELECT login_time, 
    m.MAU,
    COUNT(DISTINCT email) AS DAU
FROM #t1 d
CROSS APPLY (SELECT COUNT( DISTINCT email) AS MAU
            FROM #t1 m
            WHERE m.login_time BETWEEN DATEADD( dd, -30, d.login_time) AND d.login_time) m
GROUP BY login_time, m.MAU
ORDER BY login_time;

答案 1 :(得分:0)

感谢Luis,一个非常聪明的答案,这就是MySQL 8.X风格,以防万一,就像我一样:

drop table if exists t1;

create table t1 (email text, login_time datetime)
;
insert into t1 values 
('aa@gmail.com', '2019-03-15 00:00:00.000'),
('aa@gmail.com', '2019-04-01 00:00:00.000'),
('aa@gmail.com', '2019-04-02 00:00:00.000'),
('aa@gmail.com', '2019-04-03 00:00:00.000'),

('bb@gmail.com', '2019-03-19 00:00:00.000'),
('bb@gmail.com', '2019-04-01 00:00:00.000'),
('bb@gmail.com', '2019-04-02 00:00:00.000'),
('bb@gmail.com', '2019-04-02 00:00:00.000'),

('cc@gmail.com', '2019-03-02 00:00:00.000'),
('cc@gmail.com', '2019-04-03 00:00:00.000'),

('dd@gmail.com', '2019-03-06 00:00:00.000')

;
SELECT login_time, 
    m.MAU,
    COUNT(DISTINCT email) AS DAU
FROM t1 as d,
LATERAL (SELECT COUNT( DISTINCT email) AS MAU
            FROM t1 m
            WHERE m.login_time BETWEEN d.login_time - interval 30 day AND d.login_time) as m
GROUP BY login_time, m.MAU
ORDER BY login_time; 

关键字LATERAL(在MySQL 8.X中相当于CROSS APPLY)(表示“此派生表取决于左侧的先前表”)