头哥数据库实战答案及解析(1-6 到 1-9)

1-6 MySQL数据库 - 单表查询(三)

第一关:对查询结果进行排序

编程要求 在右侧编辑器Begin-End处补充代码,查询学生成绩表中1班同学的所有信息并以成绩降序的方式显示结果。 我们已经为你提供了学生成绩表: tb_score表数据:

stu_id class_id name score
1 2 Jack 81
2 1 David 74
3 1 Mason 92
4 2 Ethan 89
5 1 Gina 65

分析 使用 order by 字句对筛选出来的结果进行排序,基本用法: select 字段名 from 表名 order by 字段名 (DESC) 如果不加 desc 则默认为升序

USE School;
#请在此处添加实现代码
########## Begin ##########
​
########## 查询1班同学的所有信息以成绩降序的方式显示结果 ##########
select * 
from tb_score
where class_id=1
order by score desc;
​
########## End ##########

第二关:分组查询

编程要求 在右侧编辑器Begin-End处补充代码,对班级表中的班级名称进行分组查询。 我们已经为你提供了班级表信息: tb_class表数据:

stu_id class_id name
1 367 Jack
2 366 David
3 366 Mason
4 367 Ethan
5 366 Gina

分析 利用 group by 字句进行分组查询,基本用法为 select 字段名 from 表名 group by 字段名

USE School;
​
#请在此处添加实现代码
########## Begin ##########
​
########## 对班级名称进行分组查询 ##########
select * from tb_class
group by class_id
​
########## End ##########

第三关:使用 LIMIT 限制查询结果的数量

编程要求 在右侧编辑器Begin-End处补充代码,查询班级中第2名到第5名的学生信息,并根据学生成绩进行降序排序。 我们已经为你提供了学生成绩表: tb_score表数据:

id name score
1 Jack 89
2 David 73
3 Mason 62
4 Ethan 93
5 Gina 76
6 Dorris 98
7 kain 86
8 Alice 91

分析 这里涉及到多个字句的顺序问题,如果一个查询语句同时含有 group by, having, order by, limit 那么它们在 sql 语句中出现的顺序就是上述的顺序。 这个题使用到了利用 limit 实现分页查询,基本的用法为 limt 开始查询的页码-1, 需要查询的数据个数,如上题中要查询 2 到 5 的数据,limit 后面的数字就是 1 和 4。

USE School;
#请在此处添加实现代码
########## Begin ##########
​
########## 查询班级中第2名到第5名的学生信息 ##########
select * from tb_score
order by score desc
limit 1, 4;
​
########## End ##########

1-7 MySQL数据库 - 连接查询

第一关:内连接查询

编程要求 在右侧编辑器补充代码,查询数据表中学生姓名以及对应的班级名称,将其对应的列名分别另命名为studentNameclassName。 我们为你提供了两张表,内容如下: tb_student表数据:

id name class_id
1 Emma 2
2 Mary 4
3 Allen (null)
4 Kevin 1
5 Rose 2
6 James 1

tb_class`表数据:

id name
1 软件1631
2 软件1632
3 测试1631
4 测试1632

分析 这里用到了多表查询的内连接查询,可以一次查多个表,达到信息的匹配,内连接查询分为隐式的内连接和显式的内连接,一种是用返回的笛卡尔积加上 where 字句来实现筛查,另一种是利用 join on 字句来实现,两种查询方法并没有本质上的不同,只是写法有所区别。

USE School;
########## 查询数据表中学生姓名和对应的班级 ##########
########## Begin ##########
​
-- 显示的方法
select tb_student.`name` as studentName,tb_class.`name` as className 
from tb_class 
join tb_student on tb_class.id=tb_student.class_id;
​
-- 利用隐式的方法查询
select tb_student.`name` as studentName, tb_class.`name` as className
from tb_student, tb_class
where tb_student.class_id = tb_class.id;
########## End ##########

第二关:外连接查询

编程要求 在右侧编辑器补充代码,分别使用左外连接右外连接查询数据表中所有学生姓名和对应的班级名称,查询结果列分别另命名为studentNameclassName。 我们为你提供了两张表,内容如下: tb_student表数据:

id name class_id
1 Emma 2
2 Mary 4
3 Allen (null)
4 Kevin 1
5 Rose 2
6 James 1

tb_class表数据:

id name
1 软件1631
2 软件1632
3 测试1631
4 测试1632

注意:请使用 tb_student 作为左表,tb_class 作为右表。

分析 这里涉及到了外连接的知识,先来叙述一下外连接和内连接的区别: 内连接是用相同的键值来将两个表联系起来的,如果两个表中没有相同的键值则不会返回结果。 而外连接将会显示即使匹配不上的结果,不符合的会用 null 填充,如果希望左边的值显示出来,就用左外连接 left join on 反之则用 right join on

USE School;
########## 使用左外连接查询所有学生姓名和对应的班级 ##########
#请在此处添加实现代码
########## Begin ##########
select stu.name as studentName, cla.name as className
from tb_student as stu left join tb_class as cla on stu.class_id = cla.id;
########## End ##########
​
########## 使用右外连接查询所有学生姓名和对应的班级 ##########
#请在此处添加实现代码
########## Begin ##########
select stu.name as studentName, cla.name as className
from tb_student as stu right join tb_class as cla on stu.class_id = cla.id;
########## End ##########

第三关:复合条件连接查询

**编程要求 在右侧编辑器补充代码,查询所有班级里分数在90分以上的学生的姓名和学生的成绩以及学生所在的班级,其中学生的姓名和学生所在班级分别另命名为studentNameclassName。 我们为你提供了两张表,内容如下: tb_student表数据:

id name class_id score
1 Emma 2 89
2 Mary 4 92
4 Kevin 1 76
5 Rose 3 68
6 James 1 99

tb_class表数据:

id name
1 软件1631
2 软件1632
3 测试1631
4 测试1632

分析 该题用到了符合条件的查询,即对查询出来的笛卡尔积用 where 字句来限制查询的结果。

USE School;
​
########## 查询所有班级里分数在90分以上的学生的姓名和学生的成绩以及学生所在的班级 ##########
#请在此处添加实现代码
########## Begin ##########
select stu.name as studentName, score, cla.name as className
from tb_student as stu, tb_class as cla
-- 如果列名不会引起误解,则可以省略表名
where score > 90 && class_id = cla.id;
​
########## End ##########

1-8 MySQL数据库 - 子查询

第一关:带比较运算符的子查询

编程要求 在右侧编辑器补充代码,查询大于所有平均年龄的员工姓名与年龄。 我们为你提供了tb_emp表,数据如下:

id name age
1 Mary 23
2 Allen 21
3 kevin 25
4 Tom 33
5 Nancy 28

分析 这个题涉及到了子查询的知识,子查询指的是在 select 语句中出现了其他的 select 语句,这个语句既可以作为数据出现在 where 的限制条件中,也可以作为一个临时表出现在 from 后面,利用子查询可以解决很多问题。

USE Company;
#请在此处添加实现代码
########## Begin ##########
#1.查询大于所有平均年龄的员工姓名与年龄
select name, age
from tb_emp 
where age > (select avg(age) from tb_emp);
​
########## End ##########

第二关:关键字子查询

编程要求 我们为你提供了如下数据表: tb_salary表数据:

id position salary
1 Java 8000
2 Java 8400
3 Java 9000
4 Python 6500
5 Python 10000

根据提供的数据,在右侧编辑器中补充代码: 1)查询薪资表中比Java最高工资高的所有员工职位名称和薪资; 2)查询薪资表中比Java最低工资高的所有员工职位名称和薪资; 3)查询薪资表中职位为Java的所有员工职位名称和薪资。

分析 这个题涉及到了查询的关键字,适用于多行查询,all 表示所有,有些情况下可以用 max 的单行子查询代替,any 有些情况下可以用 min 的单行子查询来代替,可以把查询出来的表看作一个数据的集合来再次带入查询语句进行查询,

USE Company;
#请在此处添加实现代码
########## Begin ##########
​
#1.使用 ALL 关键字进行查询
select `position`, salary
from tb_salary
where salary > all(select salary from tb_salary where `position` = 'Java');
#2.使用 ANY 关键字进行查询
select `position`, salary
from tb_salary
where salary > any(select salary from tb_salary where `position` = 'Java');
#3.使用 IN 关键字进行查询
select `position`, salary
from tb_salary
where id in (select id from tb_salary where `position` = 'Java');
########## End ##########

1-9 MySQL数据库 - 复杂查询(一)

第一关:交换工资

编程要求 给定一张 tb_Salary 表,如下所示,有 m = 男性f = 女性的值。 交换所有的 fm 值(例如,将所有 f 值更改为 m,反之亦然)。

id name sex salary
1 Elon f 7000
2 Donny f 8000
3 Carey m 6000
4 Karin f 9000
5 Larisa m 5500
6 Sora m 500

要求只使用一句更新update语句,且不允许含有任何select语句完成任务。

分析 这个题运用到了 update 语句,以及 if 语句或者 case 语句。 先来回顾一下 update 语句,它的基本语法是 update 表名 set 列名 = 新元素。 再来说一下 if 语句的使用,相当于 Java 中的三元运算符,if(条件, 值1, 值2),如果满足条件则返回第一个值,否则返回第二个值。 再来说一下 case 的用法,基本结构为 case when 条件1 then 值1 when 条件2 then 值2 else 值3 end 可以用于不止一个条件的筛选,后面可以跟多个 when 语句。

#请在此添加实现代码
########## Begin ##########
update tb_Salary
set sex = if(sex='f', 'm', 'f');
########## End ##########

第二关:换座位

编程要求 本关任务:改变相邻俩学生的座位。 小美是一所中学的信息科技老师,她有一张 tb_Seat座位表,平时用来储存学生名字和与他们相对应的座位 idtb_Seat表结构数据如下:

id name
1 Elon
2 Donny
3 Carey
4 Karin
5 Larisa

现在小美想改变相邻俩学生的座位(若学生人数为奇数,则无需改变最后一位同学的座位),现在需要你编写SQL输出小美想要的的结果。

分析 查询语句的综合使用,先确定思路,分为两种情况,一种是最后一位是奇数,另一种是最后一位是偶数,如果是偶数的话则处理方式相同,如果是奇数的话则因该不变,因此应该写三条 case 语句,如果是偶数的话,将 id - 1,如果是奇数且不是最后一个则 id + 1,最后一种情况就是如果是奇数且是最后一位的话,则 id 不变。

#请在此添加实现代码
########## Begin ##########
select (case
      -- 当当前id是奇数并且不是最后一个id时,id+1
      when mod(id,2)!=0 and id!=counts then id+1
      -- 当当前id是奇数并且是最后一个id时,id不变
      when mod(id,2)!=0 and id=counts then id
      -- 否则,当前id是偶数,id-1
      else id-1 end)
as id, name
from tb_Seat, (select max(id) as counts from tb_Seat) as tb_Seat_counts
order by id;
########## End ##########

第三关:分数排名

编程要求 编写SQL查询来实现二种排名方式的分数排名。 score表结构信息如下:

Id Score
1 3.52
2 3.65
3 4.23
4 3.85
5 4.23
6 3.65

如果两个分数相同,则两个分数排名(Rank)相同。 情况一:平分后的下一个名次是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。例:1、1、2、3、4、4。 情况二:排名是非连续的。例:1、1、1、4、4、6。

分析 查询的综合应用,先将这个序列进行排序作为查询的表使用,再在查询中限制条件,第一种排序方法无序得到每个人当前的序号,只要决定排名是否增长即可,而第二种则需要记忆每个人当时的排序,决定增长的时候需要做转换。

-- 使用 set @来定义一个变量
set @dense_rank=0;
set @prev_score = null;
select Score,(
    case 
    when @prev_score = Score 
        then @dense_rank       # 当前分数与上一个分数相同,rank不变
    -- 利用 := 来实现判断的同时赋值
    when @prev_score := Score  # 恒为true,当不满足上一个语句时(分数不同时) 
        then @dense_rank := @dense_rank + 1
    end
)as Rank
from (select Score from score order by Score desc) as temp;
-- 第二种排序方法需要记忆每个成员的排名,重点看一下这个排序
set @rank=0;
set @prev_score = null;
select Score,(
    -- 下面进行判断,当成绩发生变化后就切换编号
    case
    when @prev_score = Score then 
        @rank
    when @prev_score := Score then 
        @rank := Id
    end 
)as Rank
from  (
    -- 进行每一次选择的时候都将它的 id 加一
    select @id:=@id+1 AS ID, Score 
    -- 将 score 和 新建的 @id 变量来拼接形成一个新的表并返回
    from score, (SELECT @id:=0) AS initorder 
    order by Score desc
)
as temp;

第四关:体育馆的人流量

编程要求 本关任务:某市建了一个新的体育馆,每日人流量信息被记录在gymnasium表中:序号 (id)、日期 (date)、 人流量 (visitors_flow)。 请编写一个查询语句,找出人流量处于高峰的记录 id、日期 date 和人流量 visitors_flow,其中高峰定义为前后连续三天人流量均不少于 100。 gymnasium表结构数据如下:

id date visitors_flow
1 2019-01-01 58
2 2019-01-02 110
3 2019-01-03 123
4 2019-01-04 67
5 2019-01-05 168
6 2019-01-06 1352
7 2019-01-07 382
8 2019-01-08 326
9 2019-01-09 99

提示:每天只有一行记录,日期随着 id 的增加而增加。

分析 复杂的查询问题,这个题有两个限制的条件,一个是连续三天,另一个是要大于一百,以上述的例子来说,5 6 7 和 6 7 8 这两组是满足条件的,但该如何将它们返回呢? 可以将表格都拼接,三个表拼接后包含了序号的所有情况,这时候我们只需要将 a 中的数据完全显示出来即可,比如 5 6 7,6 7 8,6 5 7, 6 7 5 等等,因此需要写出三种可能的情况,即 a b c 三个表中序号是三个连续天数的所有情况。

#请在此添加实现代码
########## Begin ##########
select  distinct a.* from gymnasium a,gymnasium b,gymnasium c
where a.visitors_flow>=100 and b.visitors_flow>=100 and c.visitors_flow>=100
and (
     (a.id = b.id-1 and b.id = c.id -1) or
     (a.id = b.id-1 and a.id = c.id +1) or
     (a.id = b.id+1 and b.id = c.id +1)
) order by a.id;
########## End ##########

第五关:统计总成绩

编程要求 本关任务:计算每个班的语文总成绩和数学总成绩,其中低于 60 分的成绩不记入总成绩。 tb_score结构数据:

name chinese maths
A 89 98
B 99 89
C 55 66
D 88 66
E 55 66
F 88 99

tb_class表结构数据:

stuname classname
A C1
B C2
C C3
D C2
E C1
F C3

分析 首先想到的就是将两个表组合起来,并用 group by 语句进行分组,再对分组后的表格进行操作来求取总成绩。

#请在此添加实现代码
########## Begin ##########
select 
-- as 可以省略
    classname,
    sum(if(chinese>=60,chinese,0)) chinese,
    sum(if(maths>=60,maths,0)) maths 
from tb_score a,tb_class b where a.name=b.stuname 
group by b.classname;
########## End ##########

你可能感兴趣的:(mysql,笔记,数据库,java)