select user_id, max(date) from login group by user_id order by user_id
select u.name, c.name, date from login l join user u on l.user_id = u.id join client c on l.client_id = c.id where (l.user_id, l.date) in ( select user_id, max(date) from login group by user_id ) order by u.name;
次日留存率:(第一天登录的新用户并且第二天也登录的用户)/(总用户)
首先获取总用户
select count(distinct user_id) from login
然后找到用户第一天就登录的用户
select user_id,min(date) from login group by user_id
同时找到第二天也登录的用户,我们可以通过如下来获取
select user_id,date_add(min(date),interval 1 day) from login group by user_id
select round(count(user_id) / (select count (distinct user_id) from login), 3) from login where (user_id, date) in ( select user_id, date_add(min(date), interval 1 day) from login group by user_id );
DATE_ADD(yyyy-mm-dd,INTERVAL 1 DAY)
select user_id, min(date) from login group by user_id
select date, sum( case when (user_id,date) in (select user_id, min(date)from login group by user_id) then 1 else 0 end) from login group by date order by date;
select temp1.date, round(if(first_login = 0, 0, ifnull(retain, 0) / first_login), 3) res from ( -- 每天的新增用户数 select date, sum(case when (user_id, date) in ( select user_id, min(date) from login group by user_id) then 1 else 0 end) first_login from login group by date ) temp1 left join ( -- 每天的留存用户数 select date, date_sub(date, interval 1 day) new_date, count(*) retain from login where (user_id, date) in ( select user_id, date_add(min(date), interval 1 day) from login group by user_id ) group by date ) temp2 on temp1.date = temp2.new_date order by date
with temp as ( select l.user_id,l.date,number from login l left join passing_number pn on l.user_id = pn.user_id and l.date = pn.date ) select name,date,sum(number) over(partition by name order by date) ps_num from temp join user on temp.user_id=user.id where number is not null order by date,name
round(num, 3)
select job, round(avg(score),3) avg_score from grade group by job order by avg_score desc
with temp as ( select job, round(avg(score), 3) avg_score from grade group by job order by avg_score desc ) select id, grade.job, score from temp join grade on temp.job = grade.job where temp.avg_score < grade.score order by id;
with temp as ( select id, language_id, score, dense_rank() over (partition by language_id order by score desc) rk from grade)select temp.id, name, scorefrom temp left join language on temp.language_id = language.idwhere rk <= 2order by name, score desc, id;
select job, floor(( count(*) + 1 )/ 2 ) start, floor(( count(*) + 2 )/ 2 ) endfrom gradegroup by joborder by job;
with temp as ( select job, floor((count(*) + 1) / 2) start, floor((count(*) + 2) / 2) end from grade group by job order by job)select id, temp1.job, score, rkfrom (select id, job, score, row_number() over (partition by job order by score desc) rk from grade) temp1 join temp on temp1.job = temp.jobwhere temp1.rk = temp.start or temp1.rk = temp.endorder by temp1.id;
select * from order_infowhere date > '2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')order by id;
select user_idfrom order_infowhere date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')group by user_idhaving count(user_id) >= 2order by user_id
datediff(date1,date2)
返回起始时间 date1 和结束时间 date2 之间的天数select *from order_infowhere user_id in ( select user_id from order_info where date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python') group by user_id having count(*)>=2 ) and date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python')order by id;
with tmp as ( select * from order_info where user_id in ( select user_id from order_info where date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python') group by user_id having count(*)>=2 ) and date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python') order by id)select user_id, min(date) first_buy_date, count(user_id) cntfrom tmpgroup by user_idorder by user_id;
with tmp as ( select * from order_info where user_id in ( select user_id from order_info where date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python') group by user_id having count(*)>=2 ) and date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python') order by id)select user_id, min(date), max(date), cntfrom( select user_id, date, row_number() over (partition by user_id order by date) rk, count(user_id) over(partition by user_id) cntfrom tmp )tmp2where rk<=2group by user_id, cntorder by user_id;
订单表 left join 客户端表
with tmp as ( select * from order_info where user_id in ( select user_id from order_info where date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python') group by user_id having count(*)>=2 ) and date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python') order by id)select tmp.id,is_group_buy,namefrom tmpleft join client on tmp.client_id = client.idorder by id;
IFNULL(expression, alt_value)
:如果第一个参数的表达式 expression 为 NULL,则返回第二个参数with tmp as ( select * from order_info where user_id in ( select user_id from order_info where date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python') group by user_id having count(*)>=2 ) and date>'2025-10-15' and status = 'completed' and product_name in ('C++','Java','Python') order by id)select name_n,count(*)from ( select if(is_group_buy='Yes','GroupBuy',name) name_n from tmp left join client on tmp.client_id = client.id)tmp1group by name_norder by name_n;
date_format(date,"%Y")
select job,sum(if(year(date)=2025,num,0)) cntfrom resume_infogroup by joborder by cnt desc
每一个月每个岗位收到简历的数量
是什么意思?我们就可以知道这个是按照岗位和月份进行分组,然后聚合简历数量select job,date_format(date,"%Y-%m") month,sum(num) cntfrom resume_infowhere year(date) = 2025group by job,monthorder by month desc, cnt desc
同一个月同岗位
);仔细读题,就很容易求解select tmp1.job, first_year_mon, first_year_cnt, second_year_mon, second_year_cntfrom ( select job, date_format(date, "%Y-%m") first_year_mon, sum(num) first_year_cnt from resume_info where year(date) = 2025 group by job, first_year_mon ) tmp1 join ( select job, date_format(date, "%Y-%m") second_year_mon, sum(num) second_year_cnt from resume_info where year(date) = 2026 group by job, second_year_mon) tmp2 on tmp1.job = tmp2.job and right(first_year_mon, 2) = right(second_year_mon, 2)order by first_year_mon desc, job desc
select grade, sum(number) over(order by grade)from class_grade;
select gradefrom ( select grade, #(select sum(number) from class_grade) as total, sum(number) over() total, sum(number) over (order by grade) a, sum(number) over (order by grade desc) b from class_grade ) tmpwhere a >= total / 2 and b >= total / 2order by grade
代码里面还有一点值得学习的地方,select中可以放select语句,因为聚合函数不能和非聚合字段放在一起,所以我们重写一个select查询出这个聚合值
select name, cntfrom ( select user_id, sum(grade_num) cnt from grade_info group by user_id order by cnt desc limit 1 ) tmp join user on tmp.user_id = user.id;
with 中间表名 as (select 子句)
建立临时表with tmp_table as ( select user_id, sum(grade_num) cnt from grade_info group by user_id order by cnt desc)select user_id, name, cntfrom tmp_tablejoin user on user.id = tmp_table.user_idwhere cnt = ( select max(cnt) max_cnt from tmp_table)
with tmp_table as ( select user_id, sum(grade_num) cnt from (select user_id, if(type = "reduce", -grade_num, grade_num) grade_num from grade_info) tmp1 group by user_id)select id, name, cntfrom tmp_table join user on tmp_table.user_id = user.idwhere cnt = ( select max(cnt) from tmp_table)order by id