数据结构和算法 I

数据结构和算法 I

面试题

1.数据库

  1. 数据库有两张表为user表和user_role表,执行:SELECT u.*,r.name FROM USER u LEFT JOIN user_role r ON u.id = r.user_id 之后获取到的结果为:(A)

    联查:
    	left join/right join :
    		特点:主表的所有数据均显示,另外一张表中有匹配的数据,则显示,若无匹配的数据,该字段显示为null
    	inner join:
    		特点:查询的数据是满足所有条件的数据,若没有满足所有条件的数据,则结果集为空
    user表数据:             user_role表数据:
        id username             id name user_id
        1  张三                  1 售后   1
        2  李四                  2 运维   2
        3  王五                  3 研发   3
        4  小刘                  4 实施   5 
    A.  1 张三 售后  
        2 李四 运维 
        3 王五 研发 
        4 小刘 null
    B.  1 张三 售后 
        2 李四 运维 
        3 王五 研发
    C.  1 张三 售后 
        2 李四 运维 
        3 王五 研发
        null null 实施
    
2.sql编写题:
  1. 请描述查询语句中各部分的执行顺序 – 面试

    select distinct...from t1 (left/right) join t2  on t1.xx=t2.xx where t1.xx=? and t2.xx=? group by t1.xx having ...order by ... limit ..
    
    where:  筛选条件   分组之前
    having: 筛选条件   前提:必然先分组    对分组后的结果再次筛选
    where,group by,having三者同时出现,则顺序一定为:
    	where....group by ... having ....
    	
    limit用法:
    	limit m,n   从索引m处开始,筛选n条件数据 -- 实现分页
    	limit m   从第一条数据开始,筛选前m条
    
    
    1. from  join   产生虚拟表v1  - 产生的是笛卡尔积
    	笛卡尔积:两表完全连接的结果叫做笛卡尔积,会产生m*n条数据
    2. on    根据连接条件进行筛选,基于V1,产生虚拟表v2   
    3. left/right join 若是外连接,将主表中的所有数据进行补充到v2表中
    4. where   根据查询条件,从v2中进行数据筛选,产生虚拟表v3
    5. group by  对v3分组,产生虚拟表v4
    	经常会和聚合函数配合使用,聚合函数的结果在group by之后就会产生
    	使用场景: 统计每个班级的学生人数
    		select   count(xx)  ....group by bj_id
    		    统计每个部门的人数
    		select   count(xx)  ... group by d.id
    6. having    对分组后的结果再次筛选 ,产生虚拟表v5
    7. select    选择最终要显示的字段,产生虚拟表v6
    8. distinct  对结果集进行去重,产生虚拟表v7
    9. order by  对结果根据某字段进行升序/降序排列 
    10. limit    选择需要的数据
    
       where 和having区别:
       	  where是在分组之前进行数据筛选,having是对分组后的结果再次筛选
       	  where,group by,having若同时出现,则三者的顺序一定是
       	    where在 group by之前,having在group by之后
    

    请添加图片描述

  2. 表名:stu_score

id name score bj
1 赵一 89 1班
2 钱二 88 2班
3 孙三 84 1班
4 李四 86 2班
5 王五 87 1班
6 吴六 91 2班

获取每个班级的最后一名

final.sql中最后一张表
考点:group by能查到什么
    group by cola  
    	可以查询到  分组后的cola,相关的聚合函数,与cola具有一对一关系的列,除此之外,其他字段都查询不到
正确的思路:
	1. 查询出每个班级的最低分
	2. 根据上述的查询结果,再次到stu_Score表中查询,查询某个班级最低分对应的学生是谁
	
	select ss.* from stu_score ss join 
	(select bj,min(score) min from stu_score group by bj)tmp
	on ss.score=tmp.min and ss.bj=tmp.bj
  1. 表user,字段有:id(非自增,不连续),age,name,sex,addTime。求创建时间(addTime)在2020-05-22至2020-06-17之间所有数据

    查询某段时间区间内的数据,使用between..and...  ,也可以使用>  <
    select * from user where addTime between '2020-05-22' and '2020-06-17'
     数据库中between..and两个边界值都包含
    
  2. 基于表user,查出表中第10条至第20条连续分页数据的sql语句

    select * from user limit 9,11
    
5. 有以下表以及数据,写出以下sql

student表:

sno sname sage
1 周杰伦 18
2 周润发 18
3 吴孟达 25
4 刘德华 25
5 李连杰 29
cno cname
1 语文
2 数学
3 英语
sno cno score
1 1 60
1 2 61
2 1 80

三张表分别为:student ,course,score

  1. 查询所有学生的学号,姓名,选课数,总成绩

    分析题意,得出需要使用Student表和score两表外连接查询,其中student表为主表
    从student表中查询sno,sname,选课数和总成绩查询时需要根据学号分组,必须根据是student表的sno分组,不能根据score表的sno分组.
    
    select s.sno,sname,count(cno)'选课数',ifnull(sum(score),0)'总成绩' from student s left join score sc on s.sno=sc.sno group by s.sno
    
    若结果为null,想替换为其他值,则可以使用数据库提供的函数 ifnull(exp1,exp2)
    
    count()
    	该函数中可以用* ,也可以用列名
    		count(*): 统计有多少行
    		count(sno)
    
  2. 查询没有学完所有课程的学生学号,姓名

    思路: 查询选课数<总课程数的学生
    1. 查询总课程数
    	select count(*) from course1 
    2. 统计每个学生的选课数,然后筛选选课数<总课程数的
    	select s.sno,sname from student s left join score sc on s.sno=sc.sno group by s.sno having count(cno)<(select count(*) from course1 )
    
6. 已知以下表结构

班级表(class)

编号 班级名称
id class_name
1 一班
2 二班
3 三班
4 四班
5 五班

学生表(student)

编号 学号 姓名 性别 所属班级
id stu_no stu_name stu_gender class_id
1 2020001 张三 1
2 2020002 李四 1
3 2020003 李丽 2
4 2020004 赵婷 3
5 2020005 王五 3

成绩表(score)

学生 语文 数学
stu_id chinese math
1 70 47
2 80 60
3 50 82
4 80 90

业务场景限制:

  1. 一个班级有多名学生,一名学生只属于一个班级
  2. 学生有可能没有成绩
题目:
  1. 查询所有学生的信息(学号,姓名,性别,班级名称)

    select stu_no,stu_name,stu_gender,class_name from student s join class c on s.class_id=c.id
    
  2. 查询所有人(包括没有成绩的学生)的课程分数(学号,姓名,性别,班级名称,语文分数,数学分数)

    三表联查,其中student表和class 表内联;student表和score是外连接查询
    多表联查,既有内联又有外联的语法:
    	select...from A join B on A.xx=B.xx  left join C on A.xx=C.xx
    	不要写成:
    		select..from A join B left join C on A.xx=B.xx and A.xx=C.xx
    		
    	若三表全都内联语法:
    		select..from A join B join C on A.xx=B.xx and A.xx=C.xx
    		
    		不要写成:
    			select..from A join B on A.XX=B.xx join C on A.xx=c.XX 
    				-- 语法通过,结果也是正确的
    
    select stu_no,stu_name,stu_gender,class_name,chinese,math  from student s join class c on s.class_id=c.id left join score sc on s.id=sc.stu_id
    
  3. 查询语文分数比“张三”高的学生(学号,姓名,性别,班级名称,语文分 数)

    1. 查询张三的语文分数
    	SELECT chinese FROM student s JOIN score sc ON s.id=sc.stu_id WHERE 
    stu_name='张三'
    2. 三表联查,查询语文>张三语文分的学生信息 -- 三表内联查询结果即可
    	select stu_no,stu_name,stu_gender,class_name,chinese from student s join class c join score sc on s.class_id=c.id and s.id=sc.stu_id where chinese>(SELECT chinese FROM student s JOIN score sc ON s.id=sc.stu_id WHERE 
    stu_name='张三')
    
  4. 查询各科都合格(分数>=60)的学生(学号,姓名,语文分数,数学分数)

    select stu_no,stu_name,chinese,math from student s join score sc on s.id=sc.stu_id where chinese>=60 and math>=60
    
  5. 查询班级人数>=2的班级(班级编号,班级名称,人数)

    1. 求出每个班级的人数,然后筛选人数>=2的班级 -- 注意:无需使用外连接
     select class_id,class_name,count(stu_no) cou from student s join class c on s.class_id=c.id group by class_id having cou>=2
    
4. 有一张表score,三个字段名,姓名,课程,分数,数据如下,请写一条sql语句,查询出每门课程都大于等于80分的学生信息
name course score
张三 语文 81
张三 数学 75
李四 语文 76
王五 语文 81
王五 数学 100
王五 英语 90
思路:统计每个学生的最低分,筛选最低分>=80
select name from score group by name having min(score)>=80

或者
SELECT score.* 
FROM score 
WHERE `name` 
NOT IN(
SELECT DISTINCT NAME
FROM score a
WHERE score<80)
5. 有一张表student,包括字段id和name,请写一条sql语句,将表中name字段中重复的记录删除,只保留重复数据中的id最大的那一条数据。
id name
1 张三
2 张三
3 李四
4 王五
5 王五
6 王五

要求只留下:2 张三, 3 李四, 6 王五 这三条记录

1. 查询每个学生的最大id
2. 从表中删除数据,删除条件是id不在以上值之内

delete from student1 where id not in(select max(id) from student1 group by name)
注意点:在查询结果基础上进行update操作,在mariadb10版本是支持的,在mysql5.5 mysql8都不支持
6. 学生表如下
自动编号 学号 姓名 课程编号 课程名称 分数
1 2021001 张三 0001 数学 69
2 2021002 李四 0001 数学 89
3 2021001 张三 0001 数学 69
  • 删除除了自动编号不同,其它都相同的学生冗余信息

    考点:group  by后可以加多个字段
    delete from student2 where id not in(select min(id) from student2 group by stu_no,name,course_id,course_name,score)
    
7. 有如下一张表,按照右侧的结果格式写出生成右侧结果的SQL语句

请添加图片描述

高频笔试题  
考点: case when类比与java中的if..else
case when  exp then ..
	 when  exp1  then...
	 when  exp2  then...
	 else....end

在成绩表   col:  name  course  score  显示出每个学生分数处于哪个级别(>=90 优秀  >=80 良好  >=70 中等  >=60  及格   <60 不及格  )

要求:查询每个学生的成绩,并显示级别: name  course  score  level

select name,course,score,
    (case when score>=90 then '优秀'
    when  score>=80 then '良好'
    when score>=70 then '中等'
    when score>=60 then '及格'
    ELSE '不及格' end)level
    from score 
    
case when经常和聚合函数配合使用 -- 经常考察
	要求:统计出每个学生及格和不及格的科目数
		
	select name,
	sum(case when score>=60 then 1 else 0 end)'及格科目数',
    sum(case when score<60 then 1 else 0 end)'不及格科目数' from score group by name

	
	select name,
	count(case when score>=60 then 1  end)'及格科目数',
    count(case when score<60 then 1  end)'不及格科目数' from score group by name
    
    注意点:case when 和sum()和count()使用时,用法不同(意义不同)
    	sum()配合使用,满足条件返回1,表示进行+1  else 0表示+0
    	count()配合使用,返回的值只要不是null,就进行一次计数,所以使用count()必须注意:若满足条件想进行一次计数,不满足条件不计数,应写成:
    		count(case when ....then 1 else null end)
    		或 count(case when ...then 1 end)  没有else,表示不满足条件,返回null

本题解法:
select match_date '比赛日期',
sum(case when result='胜' then 1 else 0 end)'胜',
sum(case when result='负' then 1 else 0 end)'负'
from match_record group by match_date
  1. 有如下3张表,完成如下需求:
    请添加图片描述
    (1) 用户表中添加一条数据,请写出SQL语句

(2) 在用户表中把姓名为"李四"的在职用户的年龄修改为28

(3) 查询所有的角色名称为"技术人员",性别是女的在职人员

(4) 把角色名称为"研发人员"的用户"张三"从用户表中删除

(5) 查询年龄在18到24岁之间的男性在职人员

(6)查询年龄为18,19,20的男性和女性员工的人数,结果如下图所示:

年龄
18 5 3
19 4 6
20 1 0

(7) 查询前50名姓张的男员工

(8)查询所有根角色员工,根角色就是父角色为null的角色.

9. 以下四个表,表名称及表结构如下:
student(sno,sname,sage,ssex) 学生表
course(cno,cname,tno) 课程表
sc(sno,cno,score) 成绩表
teacher(tno,tname) 教师表
  1. 查询课程1的成绩比课程2的成绩高的所有学生的信息
  2. 查询平均成绩大于60分的同学的学号和平均成绩
  3. 查询学过‘李四’老师所教课程的所有同学的学号,姓名
  4. 查询姓“李”得老师的个数
  5. 查询每门课程的选修人数(课程名称,学生数量)–存在没有人选的课程
  6. 删除“1002”同学的“1”课程的成绩
  7. 查询选修人数最多的课程(课程id,课程名称,学生数量)–考虑有多门课程都是选修最多的情况
10. 数据库表名为guest,请简答
账号 消费 时间 金额 班次
accounts details date money class
s0001 房费 2020-01-01 280 001
s0001 酒水 2020-01-02 120 001
s0001 房费 2020-01-08 300 003
s0002 酒水 2020-01-29 50
s0003 房费 2020-01-31 180 002
s0004 房费 2020-02-01 230 001
s0005 酒水 2020-02-01 100
s0005 房费 2020-02-02 128 001
  1. 查询出房费都大于200的账号
  2. 查询出1月份每个账号酒水和房费的总金额
  3. 将不是房费的班次都更改为‘001’
  4. 查询出消费都大于100的账号
3. 完成以下sql查询

下面是学生成绩表(student_score)结构说明

字段名称 字段解释 字段类型 字段长度
student_id 学号 字符 8
student_name 姓名 字符 50
student_gender 性别 字符(男/女) 4
course_id 课程号 字符 5
score 分数 数值 3
ismakeup 当前考试是否为补考 字符(补考:1;非补考:0) 2

下面是课程表(course)说明

字段名称 字段解释 字段类型 字段长度 约束
course_id 课程号 字符 5 PK
course_name 课程名 字符 30 Not null
course_desc 课程介绍 字符 60

1、查找第一次考试后所有需要补考(小于60分)的学生姓名和这门课程的名称和成绩;

2、查询每个学生第一次考试后需要补考(小于60分)的课程平均分和科目数

3、查询所有参加了补考的学生的学生姓名,课程名称,补考成绩和非补考成绩;

6. 有如下表:

emp:

empno int(员工编号) ,ename varchar(50)(员工姓名) ,job varchar(100) (工作岗位),mgr int (上级领导编号),hiredate date(雇佣日期),sal int(薪金),comm int(佣金) deptno int (部门编号)

提示:工资=薪金+佣金

dept表:

deptno int (部门编号) , dname 部门名称 loc 地点

  1. 列出在每个部门工作的员工数量,平均工资
  2. 列出所有员工的姓名,部门名称和工资
  3. 列出所有部门的详细信息和部门人数
  4. 列出各种工作的最低工资
  5. 列出各个部门的manager的最低薪金(若是manager,其job的值为manageer)
  6. 列出受雇日期早于其直接上级的所有员工
  7. 列出部门名称和这些部门的员工信息,同时列出那些没有员工的部门
  8. 列出所有‘clerk’(办事员)岗位的姓名以及部门名称
  9. 列出最低薪金大于6500的各种工作
  10. 列出在研发部工作的员工的姓名,假定不知道研发部的部门编号

我是将军;我一直都在,。!

猜你喜欢

转载自blog.csdn.net/letterljhx/article/details/127009465