我写的长垃圾代码:
select l1.date,
case when round(l4.cnt_user / count(l2.user_id),3) then round(l4.cnt_user / count(l2.user_id),3)
else round(0.000, 3) end
from login l1
left join(
-- 获取到每个用户的首次访问日期
select l2.user_id, min(l2.date) as first_date
from login l2
group by l2.user_id
)l2 on l1.user_id=l2.user_id and l1.date=l2.first_date -- 这个条件设置设置了把不是首次访问的时间置空
left join (
-- 获取到第一天访问日期后,第二天还访问的人数
select l3.date, count(t.user_id) as cnt_user, DATE_ADD(l3.date, INTERVAL -1 DAY) as next_day
from login l3
inner join (
-- 获取到每个用户的首次访问日期
select user_id, min(date) as first_date
from login
group by user_id
) as t on l3.user_id=t.user_id and l3.date=DATE_ADD(t.first_date, INTERVAL 1 DAY)
group by l3.date
)as l4 on l1.date=l4.next_day
group by l1.date暂存临时表优化一下:
with user_mindate as(
-- 获取到每个用户的首次访问日期
select user_id, min(date) as first_date
from login
group by user_id
)
-- 我:费劲千辛万苦的长代码…
select l1.date,
case when round(l4.cnt_user / count(l2.user_id),3) then round(l4.cnt_user / count(l2.user_id),3)
else round(0.000, 3) end
from login l1
left join user_mindate as l2 on l1.user_id=l2.user_id
and l1.date=l2.first_date -- 这个条件设置设置了把不是首次访问的时间置空
left join (
-- 获取到第一天访问日期后,第二天还访问的人数
select l3.date, count(t.user_id) as cnt_user, DATE_ADD(l3.date, INTERVAL -1 DAY) as next_day
from login l3
inner join user_mindate as t on l3.user_id=t.user_id and l3.date=DATE_ADD(t.first_date, INTERVAL 1 DAY)
group by l3.date
)as l4 on l1.date=l4.next_day
group by l1.date猴哥的思路(牛逼)
SELECT
a.date,
ROUND( COUNT( b.user_id ) * 1.0 / COUNT( a.user_id ), 3 ) AS p
FROM
( SELECT user_id, MIN( date ) AS date FROM login GROUP BY user_id ) a
LEFT JOIN login b ON a.user_id = b.user_id
AND b.date = DATE_ADD(a.date,INTERVAL 1 DAY)
GROUP BY
a.date UNION
SELECT
date,
0.000 AS p
FROM
login
WHERE
date NOT IN ( SELECT MIN( date ) FROM login GROUP BY user_id )
ORDER BY
date;网上其他人+猴哥,最好的方法!:
-- 其他人+猴哥第二个版本,好!
SELECT d.date,
round (IFNULL( count(l2.user_id) / count(l1.user_id), 0), 3)
FROM (SELECT date FROM login group by date ) AS d
LEFT JOIN (
SELECT user_id, min(date) as first_day -- 找出最小日期
FROM login
GROUP BY user_id
) AS l1 ON l1.first_day=d.date
LEFT JOIN(
SELECT user_id, date
FROM login
) as l2 ON l1.user_id=l2.user_id and l2.date=DATE_ADD(l1.first_day, INTERVAL 1 DAY)
GROUP BY d.date
京公网安备 11010502036488号