Mysql 如何使用SQL计算保留期?

Mysql 如何使用SQL计算保留期?,mysql,sql,Mysql,Sql,我试图计算1天、7天和2周的保留率,但我被卡住了。名为users的表具有首次登录的日期。名为logins的表包含所有后续登录的日期 我的想法是从logins表中查找“max”或最近一次登录,并查找用户第一次登录后的天数。最后,我想按首次登录日期分组,并统计1天后、7天后和14天后登录应用程序的“群组”用户数。我觉得我离这里很近,但不太近 以下是我到目前为止的情况 DESCRIBE users; Field Type Null Key Default

我试图计算1天、7天和2周的保留率,但我被卡住了。名为
users
的表具有首次登录的日期。名为
logins
的表包含所有后续登录的日期

我的想法是从
logins
表中查找“max”或最近一次登录,并查找用户第一次登录后的天数。最后,我想按首次登录日期分组,并统计1天后、7天后和14天后登录应用程序的“群组”用户数。我觉得我离这里很近,但不太近

以下是我到目前为止的情况

DESCRIBE users;
Field             Type         Null  Key  Default              Extra                        
----------------  -----------  ----  ---  -------------------  ---------------------------  
uid               int(11)      YES   MUL  (null)                                            
device_id         varchar(64)  YES        (null)                                            
install_ts        timestamp    NO         CURRENT_TIMESTAMP    on update CURRENT_TIMESTAMP  
firstlogin_ts     timestamp    NO         0000-00-00 00:00:00                               
firstpurchase_ts  timestamp    NO         0000-00-00 00:00:00            

DESCRIBE logins;
Field        Type         Null  Key  Default            Extra                        
-----------  -----------  ----  ---  -----------------  ---------------------------  
uid          int(11)      NO         (null)                                          
device_id    varchar(64)  NO         (null)                                          
login_ts     timestamp    NO         CURRENT_TIMESTAMP  on update CURRENT_TIMESTAMP  
login_count  int(11)      NO         (null)                                          
level        int(11)      NO         (null)                                          


SELECT logins.uid, 
   MAX(CAST(login_ts AS Date)) AS login_dt, 
   CAST(firstlogin_ts AS Date) AS firstlogin_dt,
   MAX(DATEDIFF(CAST(login_ts AS Date),
   CAST(firstlogin_ts AS Date))) AS retentionDays
FROM logins
LEFT JOIN users
ON logins.uid = users.uid
GROUP BY logins.uid
ORDER BY logins.uid, login_dt

uid     login_dt    firstlogin_dt  retentionDays  
------  ----------  -------------  -------------  
121043  2015-01-04  (null)         (null)         
121044  2015-01-04  (null)         (null)         
121045  2015-01-06  2015-01-01     5              
121046  2015-01-05  2015-01-01     4              
121047  2015-01-04  2015-01-01     3              
121049  2015-01-05  2015-01-01     4              
121050  2015-01-02  2015-01-01     1              
121054  2015-01-04  2015-01-01     3              
121055  2015-01-15  2015-01-01     14             
121056  2015-01-07  2015-01-01     6              
121057  2015-01-12  2015-01-01     11             
121058  2015-01-02  2015-01-01     1              
121060  2015-01-11  2015-01-01     10             
121063  2015-01-07  2015-01-01     6              
121065  2015-01-05  2015-01-01     4              
121066  2015-01-07  2015-01-01     6              
121067  2015-01-03  2015-01-01     2              
121069  2015-01-03  2015-01-01     2              
121070  2015-01-06  2015-01-01     5     

如果有任何提示,我们将不胜感激。

我假设您问题中的查询是正确的,您只需要进一步帮助即可

看起来您要做的是从第一次查询的结果中进行选择,然后计算retentionDays>=1的用户数、retentionDays>=7的用户数和retentionDays>=14的用户数

转换为SQL,将生成如下查询:

SELECT
  SUM(IF(retentionDays >= 1, 1, 0)) as 1day
  SUM(IF(retentionDays >= 7, 1, 0)) as 7days
  SUM(IF(retentionDays >= 14, 1, 0)) as 14days
FROM (
  /* your previous query */
) as computedRetentionDays;
如果您想要一个比率而不是值,可以将每个总和除以
COUNT(uid)


话虽如此,我建议您在
用户
上添加一列
lastlogin\ts
,这将使您的生活更轻松(并且此查询速度更快)

这很有效。非常感谢@rlanvin。不习惯“嵌套”(这就是它的名称吗?)查询中的查询(我相信这称为子查询?)@user2205916它称为派生表,或简称为“FORM子句中的子查询”。