a. case x1 when ‘01’ then’ 赋值 else 赋值 end
b. case when x1条件 then赋值 else 赋值 end
【例】46、查询各学生的年龄,按照出生日期来算,当前月日 < 出生年月的月日则,年龄减一
select s_birth,
(DATE_FORMAT(NOW(),'%Y')-DATE_FORMAT(s_birth,'%Y') -
(case when DATE_FORMAT(NOW(),'%m%d')<DATE_FORMAT(s_birth,'%m%d') then 1 else 0 end)) as age
from student;
【例】SQL75 考试分数(四)
查询各个岗位分数升序排列之后的中位数位置的范围,并且按job升序排序
select job
,(case when count(score)%2=0 then ceiling(count(score)/2) else ceiling(count(score)/2)
end)as start
,(case when count(score)%2=0 then ceiling(count(score)/2+1) else ceiling(count(score)/2)
end) as end
from grade
group by job
order by job;
SQL41 各用户等级的不同得分表现占比
select level,score_grade,
round(count(score)/max(total_cnt),3) as ratio
from
(
select ui.uid,level,score,
(case when score between 90 and 100 then '优' when score between 75 and 89 then '良' when score between 60 and 74 then '中' else '差' end) as score_grade,
count(score)over(partition by level) as total_cnt
from exam_record er join user_info ui using(uid)
where score is not null
)a
group by level,score_grade
order by level desc,ratio desc
【例】17、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩
注:和groupby连用,取唯一值的情况——由于group不要取唯一值会默认取第一个,很多情况下第一个由于连接的原因是null,因此这里需要取最大值or求和,也就是需要在case when的外面套一个max或者sum。只有在符合情况下有value,其余情况都是0 or null,所以要用max
SELECT
a.s_id,
max(CASE a.c_id WHEN '01' THEN a.s_score END ) 语文, -- 取max函数是因为,找到的第一个很可能是空值,需要借着找到最大的值才是答案
max(CASE a.c_id WHEN '02' THEN a.s_score END ) 数学,
max(CASE a.c_id WHEN '03' THEN a.s_score END ) 英语,
avg(a.s_score) 平均分,
b.s_name
FROM Score a JOIN Student b
ON a.s_id=b.s_id
GROUP BY a.s_id
ORDER BY 5 DESC -- 从1开始计数
SQL81 牛客的课程订单分析(五)
select -- select中的变量一定要有聚合性质
user_id,
max(case when rank_no=1 then a.date else null end) as first_buy_date,
max(case when rank_no=2 then a.date else null end) as second_buy_date,
cnt
from
(select
user_id,
date,
row_number() over(partition by user_id order by date) as rank_no,
count(*) over(partition by user_id) as cnt
from order_info
where date >= '2025-10-16'
and status = 'completed'
and product_name in('C++','Java','Python')
) a
where rank_no<=2 and cnt>=2
group by user_id
order by user_id ;
SQL26 每个6/7级用户活跃情况
首先分别对考试表和做题表提取出每条考试记录的活跃年份、活跃月份、活跃日,然后做union。再把新表和用户信息表进行右连接,保留所有用户的信息。最后在连接的基础上分组计数。
select ui.uid,
count(distinct act_month) as act_month_total,
count(distinct case when act_year=2021 then act_day else null end) as act_days_2021,
count(distinct case when act_year=2021 and tag='exam' then act_day else null end) as act_days_2021_exam,
count(distinct case when act_year=2021 and tag='practice' then act_day else null end) as act_days_2021_question
from user_info ui left join
(select uid,
year(start_time) as act_year,
date_format(start_time,'%Y%m') as act_month,
date_format(start_time,'%Y%m%d') as act_day,
'exam' as tag
from exam_record
union all
select uid,
year(submit_time) as act_year,
date_format(submit_time,'%Y%m') as act_month,
date_format(submit_time,'%Y%m%d') as act_day,
'practice' as tag
from practice_record) exam_practice
using(uid)
where level in (6,7)
group by uid
order by act_month_total desc,act_days_2021 desc
【例】SQL69 牛客每个人最近的登录日期(四)
查询每个日期登录新用户个数,并且查询结果按照日期升序排序
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) as new
from login
group by date
order by date
【例】18.查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率。及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90
select
a.c_id,a.c_name,max(b.s_score) as max,min(b.s_score)as min,avg(b.s_score)as avg_score,
(100*sum(case when b.s_score>=60 then 1 else 0 end)/count(s_id))as 及格率,
(100*sum(case when b.s_score>=70 and b.s_score<80 then 1 else 0 end)/count(s_id))as 中等率,
(100*sum(case when b.s_score>=80 and b.s_score<90 then 1 else 0 end)/count(s_id))as 优良率,
(100*sum(case when b.s_score>=90 then 1 else 0 end)/count(s_id))as 优秀率
from course a left join score b
on a.c_id = b.c_id
GROUP BY a.c_id,a.c_name
等价于if(expression,a,b)
【例】SQL19 未完成试卷数大于1的有效用户
# 等价于sum(case when submit_time is null then 1 else null end)
select uid
, sum(if(submit_time is null,1,null)) as incomplete_cnt
, sum(if(submit_time is not null,1,null)) as complete_cnt
, group_concat(distinct CONCAT(DATE_FORMAT(start_time, '%Y-%m-%d'),':',tag) separator ';') as detail
from exam_record er join examination_info ei using(exam_id)
where YEAR(start_time) = 2021
group by uid
having incomplete_cnt>1
and incomplete_cnt<5
and complete_cnt >= 1
order by incomplete_cnt desc