知识点
(1)获取系统时间
1 2 3 4 5 6 7 8 | #获取当前系统的日期时间 SELECT NOW(); # 2021-12-22 13:50:58 #获取当前系统的日期 SELECT CURDATE(); # 2021-12-22 #获取当前系统的时间 SELECT CURTIME(); # 13:53:11 |
(2)获取某年某月某日的日期
1 2 4 7 | year/month函数:year(date)=2021 and month(date)=8 date_format函数:date_format(date, "%Y-%m")="202108" date like '%2021-08%' |
示例:question_practice_detail
id | device_id | question_id | result | date |
1 | 2138 | 111 | wrong | 2021-05-03 |
2 | 3214 | 112 | wrong | 2021-05-09 |
3 | 3214 | 113 | wrong | 2021-06-15 |
4 | 6543 | 111 | right | 2021-08-13 |
5 | 2315 | 115 | right | 2021-08-13 |
6 | 2315 | 116 | right | 2021-08-14 |
7 | 2315 | 117 | wrong | 2021-08-15 |
…… |
28、运营想要计算出2021年8月每天用户练习题目的数量,请取出相应数据。
方法1:
select day(date) as day,
count(question_id) as question_cnt
from question_practice_detail
where month(date)=8 and year(date)=2021
group by date
方法2:
select day(date) as day,
count(question_id) as question_cnt
from question_practice_detail
where date like '%2021-08%'
group by date ----date换成day也可以
方法3:
select day(date) as day,
count(question_id) as question_cnt
from question_practice_detail
where date_format(date, "%Y-%m") like "2021-08"
group by date
根据示例,你的查询应返回以下结果:
day | question_cnt |
13 | 5 |
14 | 2 |
15 | 3 |
16 | 1 |
18 | 1 |
29、现在运营想要查看用户在某天刷题后第二天还会再来刷题的平均概率。请你取出相应数据。
解题思路:
次日留存率=去重的数据表中所有条目数目/去重的数据表中符合次日留存的条目数目
SELECT
COUNT(q2.device_id) / COUNT(q1.device_id) AS avg_ret
FROM
(SELECT DISTINCT device_id, date FROM question_practice_detail)as q1
LEFT JOIN
(SELECT DISTINCT device_id, date FROM question_practice_detail) AS q2
ON q1.device_id = q2.device_id AND q2.date = DATE_ADD(q1.date, interval 1 day)
--具体而言,使用两个子查询,查询出两个去重的数据表,
--并使用条件(q2.date应该是q1.date的后一天)进行筛选,
--如下所示(数据未显示完全,从左至右顺序,列表名为 q1.device_id, q1.date, q2.device_id, q2.date)
--注意,MySQL中 COUNT在对列进行计数时不统计值为 null的条目
解题思路:
-
限定条件:第二天再来。
解法1:表里的数据可以看作是全部第一天来刷题了的,那么我们需要构造出第二天来了的字 段,因此可以考虑用left join把第二天来了的拼起来,限定第二天来了的可以用 date_add(date1, interval 1 day)=date2筛选,并用device_id限定是同一个用户。
解法2:用lead函数将同一用户连续两天的记录拼接起来。先按用户分组partition by device_id,再按日期升序排序order by date,再两两拼接(最后一个默认和null拼 接),即lead(date) over (partition by device_id order by date)
平均概率:
解法1:可以count(date1)得到左表全部的date记录数作为分母,count(date2)得到右表关联上了的date记录数作为分子,相除即可得到平均概率
解法2:检查date2和date1的日期差是不是为1,是则为1(次日留存了),否则为0(次日未留存),取avg即可得平均概率。
--方法1:
select count(date2) / count(date1) as avg_ret
from (
select
distinct a.device_id,
a.date as date1,
b.date as date2
from question_practice_detail as a
left join(
select distinct device_id, date
from question_practice_detail
) as b
on a.device_id = b.device_id
and date_add(a.date, interval 1 day)=b.date
) as id_last_next_date
--方法2:
select avg(if(datediff(date2, date1)=1, 1, 0)) as avg_ret
from (
select
distinct device_id,
date as date1,
lead(date) over (partition by device_id order by date) as date2
from (
select distinct device_id, date
from question_practice_detail
) as uniq_id_date
) as id_last_next_date
返回以下结果:
avg_ret |
0.3000 |