留存率例子(待優化)
阿新 • • 發佈:2020-08-14
留存率例子(待優化)
需求:計算使用者留存率
表:user_login_detaile
資料量:10w
伺服器查詢時間:550ms
name | type | lenth |
---|---|---|
id | int | 11 |
uid | int | 10 |
os | int | 2 |
loginMethod | varchar | 100 |
mobleVerson | varchar | 50 |
channel | varchar | 50 |
isType | int | 2 |
loginTime | int | 10 |
查詢思路:
1.取出id與登入時間
--由於資料庫記憶體儲的時間均為s,所以可以使用ADDDATE格式化 select uid, date_format(ADDDATE('1970-01-01 08:00:00', INTERVAL loginTime SECOND),'%Y%m%d') loginTime from user_login_detail
2.取出所有id第一次登入時間
SELECT
uid,
min(first_day) first_day
FROM
(select
uid,
date_format(ADDDATE('1970-01-01 08:00:00', INTERVAL loginTime SECOND),'%Y%m%d') first_day
from user_login_detail
group by 1,2) a
group by 1
3.合併需要的資料
SELECT b.uid, b.loginTime, c.firstday FROM (SELECT uid, date_format(ADDDATE( '1970-01-01 08:00:00', INTERVAL loginTime SECOND), '%Y%m%d') loginTime FROM user_login_detail GROUP BY 1, 2) b LEFT JOIN (SELECT uid, min(date_format(ADDDATE( '1970-01-01 08:00:00', INTERVAL loginTime SECOND), '%Y%m%d')) firstday FROM (SELECT uid, loginTime FROM user_login_detail GROUP BY 1, 2) a GROUP BY 1 ) c ON b.uid = c.uid ORDER BY 1,2
4.取得使用者的總留存天數
SELECT uid, loginTime, firstday, DATEDIFF( loginTime, firstday ) AS loginday FROM (SELECT b.uid, b.loginTime, c.firstday FROM (SELECT uid, date_format(ADDDATE( '1970-01-01 08:00:00', INTERVAL loginTime SECOND), '%Y%m%d') loginTime FROM user_login_detail GROUP BY 1, 2) b LEFT JOIN (SELECT uid, min(date_format(ADDDATE( '1970-01-01 08:00:00', INTERVAL loginTime SECOND), '%Y%m%d')) firstday FROM (SELECT uid, loginTime FROM user_login_detail GROUP BY 1, 2) a GROUP BY 1 ) c ON b.uid = c.uid ORDER BY 1,2 ) e ORDER BY 1,2
5.根據前臺傳入時間段查詢留存率
SELECT
firstday,
sum( CASE WHEN loginday = 0 THEN 1 ELSE 0 END ) adduser,
sum( CASE WHEN loginday = 1 THEN 1 ELSE 0 END )/sum( CASE WHEN loginday = 0 THEN 1 ELSE 0 END ) day2,
sum( CASE WHEN loginday = 2 THEN 1 ELSE 0 END )/sum( CASE WHEN loginday = 0 THEN 1 ELSE 0 END ) day3,
sum( CASE WHEN loginday = 3 THEN 1 ELSE 0 END )/sum( CASE WHEN loginday = 0 THEN 1 ELSE 0 END ) day4,
sum( CASE WHEN loginday = 4 THEN 1 ELSE 0 END )/sum( CASE WHEN loginday = 0 THEN 1 ELSE 0 END ) day5,
sum( CASE WHEN loginday = 5 THEN 1 ELSE 0 END )/sum( CASE WHEN loginday = 0 THEN 1 ELSE 0 END ) day6,
sum( CASE WHEN loginday = 6 THEN 1 ELSE 0 END )/sum( CASE WHEN loginday = 0 THEN 1 ELSE 0 END ) day7,
sum( CASE WHEN loginday = 14 THEN 1 ELSE 0 END )/sum( CASE WHEN loginday = 0 THEN 1 ELSE 0 END ) day15,
sum( CASE WHEN loginday = 30 THEN 1 ELSE 0 END )/sum( CASE WHEN loginday = 0 THEN 1 ELSE 0 END ) day30
FROM
(SELECT
uid,
loginTime,
firstday,
DATEDIFF( loginTime, firstday ) AS loginday
FROM
(SELECT
b.uid,
b.loginTime,
c.firstday
FROM
(SELECT
uid,
date_format(ADDDATE( '1970-01-01 08:00:00', INTERVAL loginTime SECOND), '%Y%m%d') loginTime
FROM
user_login_detail GROUP BY 1, 2) b
LEFT JOIN
(SELECT
uid,
min(date_format(ADDDATE( '1970-01-01 08:00:00', INTERVAL loginTime SECOND), '%Y%m%d')) firstday
FROM
(SELECT
uid,
loginTime
FROM
user_login_detail
GROUP BY 1, 2) a
GROUP BY 1 ) c ON b.uid = c.uid
ORDER BY 1,2 ) e
ORDER BY 1,2 ) f
WHERE
firstday BETWEEN 20160612 AND 20160712
GROUP BY 1
ORDER BY 1