1 简单查询
- 基本的查询语句:select <列名> from 表名 where 条件- where 后的条件需要标量,不可以使用集合,若与关联子查询连用可用;
可使用逻辑运算符连接多个条件:between、and、or、in()、not(不常用)- 模糊条件查询like,常用于where后,“%”表示不定长度的字符串,“_”表示一个字符
- 已知首字符查询,where 姓名 like '猴%'
- 已知末尾字符查询,where 姓名 like '%猴'
- 已知数据中的部分字符查询,where 姓名 like '%猴%'
2 汇总分析
2.1 汇总
- sum、avg、max、min等函数可用在select,新增查询列,根据函数对列数据计算,并
且通过“as”语句对查询列命名。
- 计数汇总时,注意去重(distinct),count、distinct经常连用:
count(distinct <列名>)。
1)查询课程编号为“0002”的总成绩
- 查询条件是课程号=“0002”,总成绩:sum(成绩)
select
2)查询选了课程的学生人数
- 选了课程的学生:score表,所有学生数量(表中每个学生都有选课,课程号无空值)
- 学生人数:score表,学生会选择多个课程,使用distinct避免重复,count计数,即count(distinct 学号)
select
2.2 分组
- 对数据分组使用:group by <列名>
- 看到“各(课)”,“每(门)”考虑使用分组。
- 分组后要显示汇总结果,不能在select输入“*”
1)查询各科成绩最高和最低的分
- 各科成绩:score表,按照课程号分组
- 最高分:分组中成绩最大值;最低分:分组中成绩最小值
select
2)查询每门课程被选修的学生数
- 每门课程:score表,按课程号分组;
- 课程被选修的学生数:一个课程有多少学生选择,计算分组内学生数量,count(学号)
select
3)查询男生、女生人数
- student表,按照性别分组,分别对每个组(性别)的学号计数
select
2.3 分组结果的条件
- 使用 having 语句,用在 group by 之后:
group by <列名> having 对结果设定的条件- having 后的条件可以用汇总函数
1)查询平均成绩大于60分学生的学号
- 学生平均成绩:按照学号分组,
- 分组结果条件:分组平均成绩大于60分
select
2)查询至少选修两门课程的学生学号
- 至少选修两门课程:按照学生(学号)分组,count汇总每个学生选课数量,数量大于等于2
select
3)查询同名同姓学生名单并统计同名人数
- 同名同姓同学:按学生姓名分组
- 统计同名人数:分组后统计组内人数,即同一个姓名的人数,人数>=2表示有同姓名
select
2.4 排序
- order by <列名> desc/asc,desc降序,asc升序
- 当对多个字段排序时,按先后顺序录入,使用英文逗号分隔“,”
- limit <数字>,对排序后的结果,显示前几行
- 语句运行顺序,①from…where…group by…(having…) ②select ③order by 排序最后
1)查询不及格的课程并按课程号从大到小排列
- 不及格课程:成绩<60
- 课程号从大到小排列:按课程号降序排列
select
2)查询每门课程的平均成绩,结果按平均成绩升序排列,平均成绩相同时,按课程号降序排列
- 每门课程平均成绩:按课程分组,求每组成绩的平均值
- 排序方式:先按平均成绩升序,再按课程号降序
select
3)检索课程编号为“0004”且分数小于60的学生学号,结果按分数降序排列
- 课程编号为“0004”:where 课程号 = '0004'
- 分数小于60:成绩 < 60
- 排序:按成绩降序排列
select
4)统计每门课程的学生选修人数(超过2人的课程才统计),输出课程号和选修人数,按人数降序排列,若人数相同,按课程号升序排列
- 每门课程的学生选修人数:按照课程号分组,对学号计数,人数>2
- 排序方式:先按选课人数降序,再按课程号升序
select
5)查询两门以上不及格课程的同学的学号,以及不及格课程的平均值
- 两门以上、不及格课程的同学:按学号分组(group by),并且筛选不及格(成绩<60)的科目(where);对分组、筛选后的科目成绩计数(count),科目计数的数量>2
整理顺序:筛选不及格成绩 - 按学号分组 - 对不及格成绩计数 - 求不及格平均成绩 - 不及格课程的平均值:对分组后的数据查询平均值
select
3 复杂查询
子查询——返回多行值
- 通过一个表中的数据调取另一个表的数据;
- in与子查询连用,举例:where 学号 in 符合条件的学号
标量子查询——返回单一值
关联子查询——返回同一组符合条件的一个值
where a.学号 = b.学号
1)分组取每组小于某个值的数据
案例:查询所有课程成绩小于60分学生的学号、姓名
- 查询结果:学生学号、姓名;查询表:student;查询条件:符合条件的学号
- 子查询:对应“符合条件的学号”,where 学号 in 符合条件的学号;
条件分析:所有课程成绩<60的学生,即一个学生选的课程数<60,找到符合条件的所有学生;
查询结果:学号;查询表:score;分组:按学号分组;分组结果条件:学生选的课程数<60。
select
2)分组取每个组个数不完整的组名
案例:查询没有学全所有课的学生的学号和姓名
- 查询结果:学生的学号、姓名;查询表:student;查询条件:符合条件的学号
- 子查询1:对应“符合条件的学号”,where 学号 in 符合条件的学号;
条件分析:没有选全所有课程的学生,学生选的课程数<所有的课程数;
查询结果:学号;查询表:score;分组:按学生分组;分组结果条件:学生选的课程数<所有课程数; - 子查询2:对应“所有课程数”,是标量子查询
查询结果:课程数量;查询表:course
select
3)分组取每组个数等于定值的组名
案例:查询出只选修了两门课程的全部学生的学号和姓名
- 查询结果:学号、姓名;查询表:student;查询条件:where 学号 in 符合条件的学号
- 子查询:对应符合条件的学号,条件:只选修了两门课程
查询结果:学号;查询表:score;分组:按学生分组;分组结果条件:学生选课数=2
select
4)日期转换
案例:1990年出生的学生名单
- 查询结果:学号、姓名;查询表格:student;查询条件:出生年=1990,表格中是出生日期,将出生日期使用 year() 得到出生年份
select
TopN问题
分组取每组最大值、最小值,每组最大的N条记录。
例如:每个类别下用户最喜欢的产品是哪个?每个类别下用户点击最多的5个商品是什么?
5)分组取每组最大值
案例:按课程号分组取成绩最大值所在行的数据
- 查询结果:所有字段;查询表:score as a ;条件:按课程号分组,成绩=每组成绩的最大值
- 每组成绩最大值:
查询结果:max(成绩);查询表:score as b ;条件:a的课程号=b的课程号,
select
6)分组取每组最小值
案例:按课程号分组取成绩最小值所在行的数据
select
7)每组最大的N条记录
案例:查询各科成绩前两名记录
表格与自己表格建立联结,联结方式除了关系相等,还有其他限定条件
SELECT
4 多表查询
多表联结
inner/left/right/full join on 关系条件
- inner join 不符合关联条件的部分不选择
- left join / right join 保留左/右数据,另一个表不符合关联条件的部分为null
case 表达式
case when 条件 then 结果1 else 结果2 end
常与select连用,新增查询列
1)在表A,不在表B的数据
案例:不是近视眼的学生有谁?
select
2)联结表B,查询表A
案例:查询所有学生的学号、姓名、选课数、总成绩
select
3)条件筛选表B,查询表A
案例:查询平均成绩大于85的所有学生的学号、姓名和平均成绩
select
4)三表联结
案例:查询学生选课情况:学号、姓名、课程号、课程姓名
select
5)分组条件汇总(case表达式)
案例:查询每门课程的及格人数和不及格人数
select
6)表联结+分组条件汇总(case表达式、XX join)
案例:使用分段[100-85],[85-70],[70-60],[‹60]来统计各科成绩,分别统计:各分数段人数,课程号和课程名称
select
7)多条件表联结
案例:查询课程编号为0003且课程成绩在80分以上的学生的学号和姓名
select
8)行列互换
案例:将下表1转换为表2
select
5 提高SQL查询效率
写sql时要注意尽量减少全表搜索操作,从而提高查询效率:
1)select 子句中,尽量避免使用“*”,只提取需要的列
2)where 子句,比较符左侧避免函数,统一转移到右边实现
举例:where 成绩 + 5 › 90 (表达式在比较符号的左侧)优化成:where 成绩 › 90 – 5(表达式在比较符号的右侧)
3)尽量避免使用in、not in,in可使用 between…and 替换
举例:查看第8、9个人的学号和成绩where 学号 in (8, 9) 优化成:where 学号 between 8 and 9
4)尽量避免使用 or ,可用union替换
从成绩表中选出成绩是是88分或89分学生的学号:
select 学号
from 成绩表
where 成绩 = 88 or 成绩 = 89优化后:
select 学号 from 成绩表 where 成绩 = 88
union
select 学号 from 成绩表 where 成绩 = 89
5)使用limit子句限制返回的数据行数