赞
踩
distinct() | 去重 |
---|---|
MAX() | |
avg() | 求平均值 |
union all | 将多个查询结果合在一起,不去重 |
union | 将多个查询结果合在一起 去重 |
SUBSTRING_INDEX(profile, ‘,’, -1) | 截取最后一个,如果是 -2 就是截取最后两个 |
取表中的前几条数据
// sql 取前两条数据
select device_id from user_profile limit 0, 2;
// oracle
select * from user_profile where rownum <= 2
某个字段不为空
// is not null
SELECT device_id, gender, age, university from user_profile where age is not null
字段中包含某些文字
// 包含北京
SELECT device_id, age, university
from user_profile
where university LIKE '%北京%'
多列分组
// group by 列1, 列2
SELECT gender, university,
COUNT(1) user_num,
AVG(active_days_within_30) avg_active_day,
AVG(question_cnt) avg_question_cnt
from user_profile
group by gender, university
Group by 跟 where, having 联用
SELECT university,
AVG(question_cnt) avg_question_cnt,
AVG(answer_cnt) avg_answer_cnt
from user_profile
where age > 18
GROUP by university
HAVING AVG(question_cnt) < 5
or AVG(answer_cnt) < 20
case 函数
是一种多分支的函数,可以根据条件列表的值返回多个可能的结果表达式中的一个。可用在任何允许使用表达式的地方,但不能单独作为一个语句执行。分为:简单CASE函数搜索CASE函数
SELECT 班号 ,班名,
CASE 系号
WHEN 1 THEN '软件工程系'
WHEN 2 THEN '计算机系'
WHEN 3 THEN '物联网系'
END AS 系号,班主任号
FROM 班级表
计算测试表达式,按从上到下的书写顺序将测试表达式的值与每个WHEN子句的简单表达式进行比较。如果某个简单表达式的值与测试表达式的值相等,则返回第一个与之匹配的WHEN子句所对应的结果表达式的值。如果所有简单表达式的值与测试表达式的值都不相等,若指定了ELSE子句,则返回ELSE子句中指定的结果表达式的值;若没有指定ELSE子句,则返回NULL。
例48. 查询班级表中的学生的班号、班名、系号和班主任号,并对系号作如下处理:当系号为1时,显示 “计算机系”;当系号为2时,显示 “软件工程系”;当系号为3时,显示 “物联网系”。
SELECT 班号 ,班名,
CASE 系号
WHEN 1 THEN '软件工程系'
WHEN 2 THEN '计算机系'
WHEN 3 THEN '物联网系'
END AS 系号,班主任号
FROM 班级表
CASE
WHEN 布尔表达式1 THEN 结果表达式1
WHEN 布尔表达式2 THEN 结果表达式2 …
WHEN 布尔表达式n THEN 结果表达式n
[ ELSE 结果表达式n+1 ]
END
按从上到下的书写顺序计算每个WHEN子句的布尔表达式。返回第一个取值为TRUE的布尔表达式所对应的结果表达式的值。如果没有取值为TRUE的布尔表达式,则当指定了ELSE子句时,返回ELSE子句中指定的结果;如果没有指定ELSE子句,则返回NULL。
例48用搜索CASE来做:
SELECT 班号 ,班名,
CASE
WHEN 系号=1 THEN '软件工程系'
WHEN 系号=2 THEN '计算机系'
WHEN 系号=3 THEN '物联网系'
END AS 系号,班主任号
FROM 班级表
例49.查询“M01F011”号课程的考试情况,列出学号、课程号和成绩,同时将百分制成绩显示为等级。
SELECT 学号,课程号,
CASE
WHEN 成绩 >= 90 THEN '优'
WHEN 成绩 BETWEEN 80 AND 89 THEN '良'
WHEN 成绩 BETWEEN 70 AND 79 THEN '中'
WHEN 成绩 BETWEEN 60 AND 69 THEN '及格'
WHEN 成绩 <60 THEN '不及格'
END 成绩
FROM 成绩表
WHERE 课程号 = 'M01F011'
例50.统计每个班男生和女生的数量各是多少,统计结果的表头为,班号,男生数量,女生数量。
SELECT 班号,
COUNT(CASE WHEN 性别=‘男’ THEN ‘男’ END) 男生数,
COUNT(CASE WHEN 性别=‘女’ THEN ‘女’ END) 女生数
FROM 学生表 GROUP BY 班号
例51.判断成绩的等级,85-100为“优”,70-84为“良”,60-69为“及格”,60以下为“不及格”,并统计每一等级的人数。
SELECT
CASE
WHEN GRADE BETWEEN 85 AND 100 THEN '优'
WHEN GRADE BETWEEN 70 AND 84 THEN '良'
WHEN GRADE BETWEEN 60 AND 69 THEN '及格'
ELSE '不及格'
END 等级, COUNT(*) 人数
FROM SC
GROUP BY
CASE
WHEN GRADE BETWEEN 85 AND 100 THEN '优'
WHEN GRADE BETWEEN 70 AND 84 THEN '良'
WHEN GRADE BETWEEN 60 AND 69 THEN '及格'
ELSE '不及格'
END
题目:现在运营想要将用户划分为25岁以下和25岁及以上两个年龄段,分别查看这两个年龄段用户数量
SELECT CASE WHEN age < 25 OR age IS NULL THEN '25岁以下'
WHEN age >= 25 THEN '25岁及以上'
END age_cut,COUNT(*)number
FROM user_profile
GROUP BY age_cut
示例:user_profile
根据示例,你的查询应返回以下结果:
日期函数
DateOfWeek(‘1997-06-19’) | 这天是周几:0是周一,6是周日 |
---|---|
WeekDay(‘1997-06-19 14:19:00’) | 当前时间是周几:0周一 |
DayOfMonth(‘1997-06-19’) | 这天是几号 19 |
DayOfYear(‘1997-06-19’) | 这天是一年中的第几天 |
Year(date) | 获取年份 |
Month(date) | 获取月份 |
DayName(date) | 返回星期的英文名 |
MonthName(date) | 返回月份的英文名 |
Quarter(date) | 返回季度 1~4 |
Week(date) | 返回这一周是一年中的第几周 0~52 |
Week(date,first) | 返回这一周是一年中的第几周,但是可以指定从周几开始,first = 0 从周日开始, first = 1 从周一开始 |
Hour(time) | 返回当前时间是第几小时 0~23 |
Minute(time) | 0~59 |
Second(time) | 0~59 |
Period_add(P,N) | 增加N个月到阶段P(以格式YYMM或YYYYMM)。以格式YYYYMM返回值。注意阶段参数P不是日期值。 |
例如:若返回 199706
select PERIOD_ADD(9704,2) |
| Period_diff(P1,P2) | 返回在时期P1和P2之间月数,P1和P2应该以格式YYMM或YYYYMM。注意,时期参数P1和P2不是日期值。 且p1 > p2返回是正
例如:求97年6月到 00年8月之间有几个月
select PERIOD_DIFF(200008, 9706); |
窗口函数
与group by 的区别
group by 分组后会去重,减少原表的行数
而窗口函数可以分组但不会·去重,不会改变原表的行数;并且可以排序
窗口函数只能写在select后面
窗口函数分类
区别:
学号 | 分数 | 班级 |
---|---|---|
1 | 99 | 1 |
2 | 98 | 1 |
3 | 99 | 2 |
4 | 97 | 2 |
5 | 99 | 1 |
6 | 100 | 2 |
/*
partition by 后面跟分组的列名
order by 后跟排序的列名
*/
select *,
rank() over (partition by 班级 order by 分数 desc) as ranking,
dense_rank() over (partition by 班级 order by 分数desc) as dese_rank,
row_number() over (partition by 班级 order by 分数desc) as row_num
from table_name
结果:
学号 | 分数 | 班级 | ranking | dese_rank | row_num |
---|---|---|---|---|---|
6 | 99 | 1 | 1 | 1 | 1 |
1 | 99 | 1 | 1 | 1 | 2 |
3 | 98 | 1 | 3 | 2 | 3 |
5 | 100 | 2 | 1 | 1 | 1 |
2 | 100 | 2 | 1 | 1 | 2 |
4 | 97 | 2 | 3 | 2 | 3 |
连接查询
内连接:结果只包含符合条件的行
显示内连接
select difficult_level,
# avg(if(qpd.result='right', 1, 0)) as correct_rate
# sum(if(qpd.result='right', 1, 0)) / count(qpd.question_id) as correct_rate
count(if(qpd.result='right', 1, null)) / count(qpd.question_id) as correct_rate
from user_profile as up
inner join question_practice_detail as qpd
on up.device_id = qpd.device_id
inner join question_detail as qd
on qd.question_id = qpd.question_id
where up.university = '浙江大学'
group by qd.difficult_level
order by correct_rate asc;
隐式内连接
select difficult_level,
avg(if(qpd.result='right', 1, 0)) as correct_rate
# sum(if(qpd.result='right', 1, 0)) / count(qpd.question_id) as correct_rate
# count(if(qpd.result='right', 1, null)) / count(qpd.question_id) as correct_rate
from user_profile as up, question_practice_detail as qpd, question_detail as qd
where up.university = '浙江大学'
and up.device_id = qpd.device_id
and qd.question_id = qpd.question_id
group by qd.difficult_level
order by correct_rate asc;
外连接:连接结果包含符合条件的行,也包括不符合条件的行
左外连接:以左表为基准,左表全部展示,右表符合条件的展示,不符合条件的为null
SELECT COUNT(date2) / COUNT(date1) AS avg_ret
FROM
(SELECT DISTINCT device_id, date AS date1
FROM question_practice_detail) AS qpd1
LEFT join
(SELECT DISTINCT device_id, date AS date2
FROM question_practice_detail) AS qpd2
ON qpd1.device_id = qpd2.device_id
and date2 = DATE_ADD(date1, interval 1 day)
右外连接: 以右表为基准,右表全部展示,左表符合条件的展示,不符合条件的为null
SELECT COUNT(date2) / COUNT(date1) AS avg_ret
FROM
(SELECT DISTINCT device_id, date AS date2
FROM question_practice_detail) AS qpd2
right join
(SELECT DISTINCT device_id, date AS date1
FROM question_practice_detail) AS qpd1
ON qpd1.device_id = qpd2.device_id
and date2 = DATE_ADD(date1, interval 1 day)
SQL24 统计每个用户的平均刷题数
题目:运营想要查看参加了答题的山东大学的用户在不同难度下的平均答题题目数,请取出相应数据
示例:user_profile
示例:答题明细表question_practice_detail
示例:question_detail
根据示例,你的查询应返回以下结果:
分析: 限定条件: university = '山东大学' 不同难度: 按照题目难度分类 平均刷题数: 总题目 / 总人数 SELECT up.university, qd.difficult_level, COUNT(qpd.question_id) / COUNT(DISTINCT qpd.device_id) FROM question_practice_detail qpd left JOIN user_profile up on up.device_id = qpd.device_id left JOIN question_detail qd on qpd.question_id = qd.question_id WHERE up.university = '山东大学' GROUP BY qd.difficult_level
统计每个学校各难度的用户平均刷题数
题目:运营想要计算每个学校用户不同难度下的用户平均答题题目数情况,请你取出相应数据
用户信息表:user_profile
题库练习明细表:question_practice_detail
表:question_detail
根据示例,你的查询应返回以下结果:
分析: 每个学校:按学校名分类 各个难度:按题目难度分类 平均刷题数:总题目除以总人数 注意谁是主表 SELECT us.university, qd.difficult_level, COUNT(qpd.question_id) / COUNT(DISTINCT qpd.device_id) avg_answer_cnt FROM question_practice_detail qpd LEFT JOIN user_profile us on us.device_id = qpd.device_id LEFT JOIN question_detail qd on qd.question_id = qpd.question_id GROUP BY university, difficult_level
SQL25 查找山东大学男生的GPA
题目:现在运营想要分别查看学校为山东大学或者性别为男性的用户的device_id、gender、age和gpa数据,请取出相应结果,结果不去重。
示例:user_profile
根据示例,你的查询应返回以下结果:
分析
分别查看: union all
限定条件:学校为山东大学 or 性别为男性
SELECT device_id, gender, age, gpa
FROM user_profile up
where up.university = '山东大学'
UNION ALL
SELECT device_id, gender, age, gpa
FROM user_profile up
where up.gender = 'male'
SQL26 计算25岁以上和以下的用户数量
题目:现在运营想要将用户划分为25岁以下和25岁及以上两个年龄段,分别查看这两个年龄段用户数量
本题注意:age为null 也记为 25岁以下
示例:user_profile
根据示例,你的查询应返回以下结果:
分析:
使用case函数
SELECT
case
when age < 25 or isnull(age) then '25岁以下'
when age >= 25 then '25岁及以上'
end age_cut,
count(*) number
FROM user_profile
GROUP BY age_cut;
SQL27 查看不同年龄段的用户明细
题目:现在运营想要将用户划分为20岁以下,20-24岁,25岁及以上三个年龄段,分别查看不同年龄段用户的明细情况,请取出相应数据。(注:若年龄为空请返回其他。)
示例:user_profile
根据示例,你的查询应返回以下结果:
SELECT device_id, gender,
case
when age < 20 then '20岁以下'
when age between 20 and 24 then '20-24岁'
when age >= 25 then '25岁及以上'
else '其他'
END age_cut
from user_profile
SQL28 计算用户8月每天的练题数量
题目:现在运营想要计算出2021年8月每天用户练习题目的数量,请取出相应数据。
示例:question_practice_detail
根据示例,你的查询应返回以下结果:
SELECT DAY(date) day, count(question_id) question_cnt
from question_practice_detail
where MONTH(date) = 8 and YEAR(date) = 2021
GROUP by day;
SQL29 计算用户的平均次日留存率
题目:现在运营想要查看用户在某天刷题后第二天还会再来刷题的平均概率。请你取出相应数据。
示例:question_practice_detail
根据示例,你的查询应返回以下结果:
avg_ret |
---|
0.3000 |
SELECT COUNT(DISTINCT qpd2.device_id) / COUNT(DISTINCT qpd1.device_id) AS avg_ret FROM question_practice_detail qpd1 LEFT join (SELECT * from question_practice_detail) AS qpd2 ON qpd1.device_id = qpd2.device_id and qpd2.date = DATE_ADD(qpd1.date, interval 1 day) /* 错误 在连接的时候就要去重,而不是查询的时候去重 */ 正确实例 SELECT COUNT(date2) / COUNT(date1) AS avg_ret FROM (SELECT DISTINCT device_id, date AS date1 FROM question_practice_detail) AS qpd1 LEFT join (SELECT DISTINCT device_id, date AS date2 FROM question_practice_detail) AS qpd2 ON qpd1.device_id = qpd2.device_id and date2 = DATE_ADD(date1, interval 1 day)
SQL30 统计每种性别的人数
题目:现在运营举办了一场比赛,收到了一些参赛申请,表数据记录形式如下所示,现在运营想要统计每个性别的用户分别有多少参赛者,请取出相应结果
示例:user_submit
根据示例,你的查询应返回以下结果:
gender | number |
---|---|
male | 2 |
female | 3 |
select
SUBSTRING_INDEX(profile, ',', -1) AS gender,
COUNT(1) number
from user_submit us
GROUP BY gender
SQL32 截取出年龄
题目:现在运营举办了一场比赛,收到了一些参赛申请,表数据记录形式如下所示,现在运营想要统计每个年龄的用户分别有多少参赛者,请取出相应结果
示例:user_submit
根据示例,你的查询应返回以下结果:
/*套娃*/
select SUBSTRING_INDEX(
SUBSTRING_INDEX(profile, ',', -2), ',', 1) as age, COUNT(1) AS number
from user_submit
GROUP BY age
SQL33 找出每个学校GPA最低的同学
题目:现在运营想要找到每个学校gpa最低的同学来做调研,请你取出每个学校的最低gpa。
示例:user_profile
根据示例,你的查询结果应参考以下格式:
/*
窗口函数
*/
SELECT device_id,university,gpa
FROM
(SELECT *,
RANK() over (PARTITION BY university ORDER BY gpa) ranking /* 不能直接记为rank*/
FROM user_profile) us
WHERE us.ranking = 1;
SQL34 统计复旦用户8月练题情况
题目: 现在运营想要了解复旦大学的每个用户在8月份练习的总题目数和回答正确的题目数情况,请取出相应明细数据,对于在8月份没有练习过的用户,答题数结果返回0.
示例:用户信息表user_profile
根据示例,你的查询应返回以下结果:
/*
限定条件:university = '复旦大学'
分组条件:up.device_id
*/
select up.device_id, up.university,
count(question_id) as question_cnt,
sum(if(qpd.result='right', 1, 0)) as right_question_cnt
from question_practice_detail as qpd
RIGHT join user_profile as up
on qpd.device_id = up.device_id and month(qpd.date) = 8
where up.university = '复旦大学'
group by up.device_id
SQL35 浙大不同难度题目的正确率
题目:现在运营想要了解浙江大学的用户在不同难度题目下答题的正确率情况,请取出相应数据,并按照准确率升序输出。
示例: user_profile
示例: question_practice_detail
示例: question_detail
根据示例,你的查询应返回以下结果:
/*
限定条件:浙江大学
不同难度下: 根据题目难度分组
为了避免某些字段为null也会被统计,采用内连接
*/
select difficult_level,
avg(if(qpd.result='right', 1, 0)) as correct_rate
# sum(if(qpd.result='right', 1, 0)) / count(qpd.question_id) as correct_rate
# count(if(qpd.result='right', 1, null)) / count(qpd.question_id) as correct_rate
from user_profile as up, question_practice_detail as qpd, question_detail as qd
where up.university = '浙江大学'
and up.device_id = qpd.device_id
and qd.question_id = qpd.question_id
group by qd.difficult_level
order by correct_rate asc;
SQL37 查找后多列排序
题目:现在运营想要取出用户信息表中的年龄和gpa数据,并先按照gpa升序排序,再按照年龄升序排序输出,请取出相应数据。
用户信息表:user_profile
你的查询应返回以下结果:
SELECT device_id, gpa, age
FROM user_profile
ORDER BY gpa, age ASC
SQL39 21年8月份练题总数
题目: 现在运营想要了解2021年8月份所有练习过题目的总用户数和练习过题目的总次数,请取出相应结果
示例:question_practice_detail
根据的示例,你的查询应返回以下结果:
/*
限定条件: 2021年8月份
所有练习过的题目:不需要分类
*/
SELECT COUNT(DISTINCT device_id) AS did_cnt,
COUNT(question_id) AS question_cnt
from question_practice_detail
where YEAR(date) = 2021 and MONTH(date) = 8
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。