SQL练习题解
- 一.单表查询(非技术快速入门)
- 1.基础查询
- SQL1 查询所有列
- SQL2 查询多列
- SQL3 查询结果去重
- SQL4 查询结果限制返回行数
- SQL5 将查询后的列重新命名
- SQL6 查找学校是北大的学生信息
- SQL7 查找年龄大于24岁的用户信息
- SQL8 查找某个年龄段的用户信息
- SQL9 查找除复旦大学的用户信息
- SQL10 用where过滤空值练习
- SQL11找到男性且GPA在3.5以上(不包括3.5)的用户
- SQL12 找到学校为北大或GPA在3.7以上(不包括3.7)的用户
- SQL13 找到学校为北大、复旦和山大的同学
- SQL14 找到gpa在3.5以上(不包括3.5)的山东大学用户 或 gpa在3.8以上(不包括3.8)的复旦大学同学
- SQL15 查看学校名称中含北京的用户
- SQL16 复旦大学学生gpa最高值
- SQL17 男性用户有多少人以及他们的平均gpa是多少
- SQL18 分组计算练习题
- SQL19 分组过滤练习题
- SQL20 分组排序练习题
- 二.多表查询
- 题目整理
一.单表查询(非技术快速入门)
1.基础查询
SQL1 查询所有列
SELECT id, device_id, gender, age, university, province FROM user_profile;
SQL2 查询多列
SELECT device_id, gender, age, university from user_profile
SQL3 查询结果去重
select distinct university from user_profile;
SQL4 查询结果限制返回行数
select device_id from user_profile limit 2
SQL5 将查询后的列重新命名
select device_id as user_infos_example from user_profile limit 2 offset 0
SQL6 查找学校是北大的学生信息
select device_id, university from user_profile where university = '北京大学'
SQL7 查找年龄大于24岁的用户信息
select device_id, gender, age, university from user_profile where age > 24
SQL8 查找某个年龄段的用户信息
select device_id, gender, age from user_profile where age between 20 and 23
select device_id, gender, age from user_profile where age >= 20 and age <= 23
SQL9 查找除复旦大学的用户信息
select device_id,gender,age,university from user_profile where university !='复旦大学';
SELECT device_id,gender,age,university from user_profile where university <> '复旦大学';
SELECT device_id,gender,age,university from user_profile where university not in ('复旦大学');
## 模糊查询
SELECT device_id,gender,age,university from user_profile where university not like '%复旦%';
SQL10 用where过滤空值练习
select device_id, gender, age, university from user_profile where age is not null
select device_id, gender, age, university from user_profile where age != ''
SQL11找到男性且GPA在3.5以上(不包括3.5)的用户
select device_id, gender, age, university, gpa from user_profile where gpa > 3.5 AND gender = 'male'
SQL12 找到学校为北大或GPA在3.7以上(不包括3.7)的用户
select device_id, gender, age, university, gpa from user_profile where university = '北京大学' or gpa > 3.7
SQL13 找到学校为北大、复旦和山大的同学
select device_id, gender, age, university, gpa from user_profile where university in ('北京大学','复旦大学','山东大学');
SQL14 找到gpa在3.5以上(不包括3.5)的山东大学用户 或 gpa在3.8以上(不包括3.8)的复旦大学同学
--时间长
select device_id,gender,age,university,gpa from user_profile where university='山东大学' and gpa>3.5 or university='复旦大学' and gpa>3.8
-- 子查询,麻烦, 但时间短
select device_id,gender, age,university,gpa from user_profile
where device_id in (select device_id from user_profile where university = '山东大学' and gpa > 3.5)
or device_id in (select device_id from user_profile where university = '复旦大学' and gpa > 3.8)
SQL15 查看学校名称中含北京的用户
select device_id,age,university from user_profile where university like '%北京%'
SQL16 复旦大学学生gpa最高值
select gpa from user_profile where university = '复旦大学' order by gpa desc limit 1
select max(gpa) as gpa from user_profile where university = '复旦大学'
SQL17 男性用户有多少人以及他们的平均gpa是多少
select
count(gender) as male_num,
round(avg(gpa), 1) as avg_gpa
from user_profile where gender="male";
SQL18 分组计算练习题
select gender, university,
count(device_id) as user_num,
round(avg(active_days_within_30), 1) as avg_active_day,
round(avg(question_cnt), 1) as avg_question_cnt
from user_profile
group by gender, university
SQL19 分组过滤练习题
select
university,
round(avg(question_cnt),3) as avg_question_cnt,
round(avg(answer_cnt),3) as avg_answer_cnt
from user_profile
group by university
having avg_question_cnt < 5 or avg_answer_cnt < 20
SQL20 分组排序练习题
select
university,
round(avg(question_cnt), 4) as avg_question_cnt
from user_profile
group by university
order by avg_question_cnt asc
二.多表查询
(说在前面)复杂SQL的三段式结构
以SQL23 统计每个学校各难度的用户平均刷题数为例
# 第一段:select选择字段,含原生字段及构造字段,
#其中构造的过程中常用sum count round +-*/ 等函数及运算表达式
select
university,
difficult_level,
round(count(qpd.question_id) / count(distinct qpd.device_id),4) as avg_answer_cnt
# 第二段:from选择表格,含合并表格操作
from question_practice_detail as qpd
join user_profile as up
on up.device_id=qpd.device_id
join question_detail as qd
on qd.question_id=qpd.question_id
# 第三段:数据操作段,含 分组/排序/筛选/取指定行数等操作
group by university,difficult_level;
多表查询方法一: 左连接 内连接 右连接 左外连接 右外连接
- 技术上:
在这里插入图片描述 - 业务上:
业务上多表查询的时候选择哪种取决于你想要保留什么:- 想要左表中的所有数据----左连接
- 想要右表中的所有数据----右连接
- 想要左右两张表都存在的特殊数据----内连接
- 只想要左边的且其所有字段
都不为null
----左外连接 - 只想要右边的且其所有字段
都不为null
----右外连接
多表查询方法二:子查询
类似下面这种方式就是嵌套子查询
select device_id,gender, age,university,gpa from user_profile
where device_id in (select device_id from user_profile where university = '山东大学' and gpa > 3.5)
or device_id in (select device_id from user_profile where university = '复旦大学' and gpa > 3.8)
- 什么时候多表查询不能用子查询
例如SQL22题中university
和round(count(question_id) / count(distinct qpd.device_id), 4)
这两个字段不在同一张表里
, 必须靠链接两张表生成中间表
,在中间表中查询;
因此不能用子查询
了,如果两个字段在同一张表的话就可以用子查询类似device_id in (select device_id from xx where ....)
非聚合字段和聚合函数同时出现,要用group by
什么是非聚合字段
-
在MySQL中,非聚合字段指的是不参与聚合函数计算的字段。我们有一个学生表,其中包含学生的姓名、年龄、性别、班级等信息,我们需要统计每个班级的学生数量,那么班级字段就是聚合字段,而姓名、年龄、性别等字段就是非聚合字段。
-
非聚合字段的作用非聚合字段在实际应用中非常重要,它们可以用于数据的筛选、排序和分组等操作。我们需要查询年龄大于18岁且性别为女性的学生信息,那么年龄和性别字段就是非聚合字段,在查询语句中需要使用WHERE子句进行筛选。
-
如何使用非聚合字段在MySQL中,使用非聚合字段的方法非常简单,只需要在SELECT语句中将需要查询的字段列出即可。我们需要查询学生表中的姓名、年龄和性别字段,那么查询语句如下:SELECT 姓名,年龄,性别 FROM 学生表;如果需要对查询结果进行排序,可以使用ORDER BY子句,例如按照年龄从小到大排序:
SELECT 姓名,年龄,性别 FROM 学生表 ORDER BY 年龄 ASC
;如果需要对查询结果进行分组,可以使用GROUP BY子句,例如按照班级分组统计学生数量:SELECT 班级,COUNT(*) FROM 学生表 GROUP BY 班级;
-
总结:非聚合字段在MySQL中的作用非常重要,它们可以用于数据的筛选、排序和分组等操作。在使用非聚合字段时,只需要在SELECT语句中将需要查询的字段列出即可,同时可以使用ORDER BY和GROUP BY子句对查询结果进行排序和分组。
非聚合字段和聚合函数同时出现要使用group by
select s.s_id,avg(s.s_score) as avgscore from score s group by s_id
只有聚合函数时,不用group by
select avg(s.s_score) as avgscore from score s
(2表))SQL21 浙江大学用户题目回答情况(含on 和 where的区别)
在多表查询时,on和where都表示筛选条件,on先执行
,where后执行
。
区别:
外连接时,on
条件是在生成临时表时
使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。而where
条件是在临时表生成好后
,再对临时表进行过滤的条件。
下面这题是内连接
,因此on和where的运行结果相同
链接
--内连接法
select
qpd.device_id,
qpd.question_id,
qpd.result
from question_practice_detail as qpd inner join user_profile as up
on up.device_id = qpd.device_id and up.university='浙江大学'
order by qpd.question_id asc
--子查询法
select
device_id,
question_id,
result
from question_practice_detail
where device_id in(
select device_id from user_profile
where university='浙江大学'
)
(2表)SQL22 统计每个学校的答过题的用户的平均答题数
链接
select
university,
round(count(question_id) / count(distinct qpd.device_id), 4) as avg_answer_cnt
from user_profile as up
inner join question_practice_detail as qpd
on up.device_id = qpd.device_id
group by university
本题university
和round(count(question_id) / count(distinct qpd.device_id), 4)
这两个字段不在同一张表里
, 必须靠链接两张表生成中间表
,在中间表中查询;
因此不能用子查询
了,如果两个字段在同一张表的话就可以用子查询类似device_id in (select device_id from xx where ....)
(3表)SQL23 统计每个学校各难度的用户平均刷题数
重命名字段或表
的时候用不用as都行:
例如重命名表的时候:user_profile as up
和user_profile up
都行
例如重命字段的时候:university as u
和university u
都行
----连接三张表, 这里用left join或join(inner join)或right join都行, 因为两边每个id都有, 不存在有一行其他字段为null的情况;
select
university,
difficult_level,
round(count(qpd.question_id) / count(distinct qpd.device_id), 4) as avg_answer_cnt
from question_practice_detail as qpd
left join user_profile as up
on up.device_id=qpd.device_id
left join question_detail as qd
on qd.question_id=qpd.question_id
group by university, difficult_level
----直接暴力用where
SELECT
university,
difficult_level,
COUNT(q_p.question_id) / COUNT(DISTINCT q_p.device_id) avg_answer_cnt
FROM user_profile u,
question_detail q,
question_practice_detail q_p
WHERE
u.device_id = q_p.device_id
and q_p.question_id = q.question_id
GROUP BY
university,difficult_level;
题目整理
1.字符匹配
一般形式为:
例23.查询学生表中姓‘张’的学生的详细信息。
SELECT * FROM 学生表 WHERE 姓名 LIKE ‘张%’
例24.查询姓“张”且名字是3个字的学生姓名。
SELECT * FROM 学生表 WHERE 姓名 LIKE '张__’
如果把姓名列的类型改为nchar(20),在SQL Server 2012中执行没有结果。原因是姓名列的类型是char(20),当姓名少于20个汉字时,系统在存储这些数据时自动在后边补空格,空格作为一个字符,也参加LIKE的比较。可以用rtrim()去掉右空格。
SELECT * FROM 学生表 WHERE rtrim(姓名) LIKE '张__'
例25.查询学生表中姓‘张’、姓‘李’和姓‘刘’的学生的情况。
SELECT * FROM 学生表 WHERE 姓名 LIKE '[张李刘]%’
例26.查询学生表表中名字的第2个字为“小”或“大”的学生的姓名和学号。
SELECT 姓名,学号 FROM 学生表 WHERE 姓名 LIKE '_[小大]%'
例27.查询学生表中所有不姓“刘”的学生。
SELECT 姓名 FROM 学生 WHERE 姓名 NOT LIKE '刘%’
例28.从学生表表中查询学号的最后一位不是2、3、5的学生信息。
SELECT * FROM 学生表 WHERE 学号 LIKE '%[^235]'