查询关键字 多表查询思路 可视化软件navicat 多表练习查询题

2022.5.6 查询关键字补充、多表查询思路、可视化软件navicat

  • 查询关键字
  • 多表查询思路
  • 可视化软件navicat
  • 多表练习查询题

一、查询关键字

  • 查询关键字之having过滤
  • 查询关键字之distinct去重
  • 查询关键字之order by排序
  • 查询关键字之limit分页
  • 查询关键字之regexp正则

1、查询关键字之having过滤

having与where的功能是一模一样的,都是对数据进行筛选;
	where用在分组之前的筛选;
  	havng用在分组之后的筛选;
为了更好的区分 所以将where说成筛选,havng说成过滤;

# 统计每个部门年龄在30岁以上的员工的平均薪资并且保留平均薪资大于10000的部门
	1.先获取每个部门年龄在30岁以上的员工的平均薪资
    # 获取每个部门要按部门分组,分组之前筛选30岁以上用where
    select post,avg(salary) from emp where age>30 group by post;
    2.在过滤出平均薪资大于10000的数据
    # 分组之后筛选数据用having
    select post,avg(salary) from emp 
    where age>30 
    group by post 
    having avg(salary)>10000;
    
     '''针对聚合函数 如果还需要在其他地方作为条件使用 可以先起别名'''
    select post,avg(salary) as avg_salary from emp 
    where age>30 
    group by post
    having avg_salary > 10000
    ;

2、查询关键字之distinct去重

# 去重的前提,数据必须是一样的才可以(如果数据有主键肯定无法去重)
select distinct age from emp;


"""
注意!
等我们学到django orm之后,数据会被封装成对象;
那个时候主键很容易被我们忽略,从而导致去重没有效果!!!
"""

3、查询关键字之order by排序

order by 字段 (asc/desc)

# 1.按照薪资高低排序
	select * from emp order by salary asc;  # 关键字asc,可以省略,不写默认是asc升序 
	select * from emp order by salary desc;  # 降序(从大到小)

# 2.先按照年龄升序排序,其中如果年龄相同,则再按照薪资降序排序
	select * from emp order by age asc,salary desc  # 后面再加一个代表对第一次排序后重复的进行二次排序
    
# 3.统计各部门年龄在10岁以上的员工平均工资,并且保留平均工资大于1000的部门并按照从大到小的顺序排序
	select post,avg(salary) as avg_salary from emp 
    where age>10 
    group by post 
    having avg_salary>1000 
    order by avg_salary desc;

4、查询关键字之limit分页

用于分页限制展示条数

limit 数字(限制展示5条数据)

limit 数字,数字(从第几个数字开始往后开始展示几个数字)

# 1.限制只展示五条数据
	select * from emp limit 5;
# 2.分页效果
	select * from emp limit 5,5;  # 从第6个开始展示6条数据
# 3.查询工资最高的人的详细信息
	select * from emp order by salary desc limit 1;  # 先排序然后限制展示第一个
    
"""
当数据特别多的时候 经常使用limit来限制展示条数 节省资源 防止系统崩溃
"""

5、查询关键字之regexp正则

条件>>>: 字段 regexp '正则表达式'

select * from emp where name regexp '^j.*(n|y)$'  # 晒徐娜以j开头,以n或y结尾的不限长度的字段name对应的值

"""
补充说明:我们目前所讲的是MySQL查询关键字中使用频率较高的一些;
其实还有一些关键字目前无需讲解,并且SQL语句里面同样还支持流程控制语法;
可自行研究
"""

二、多表查询思路

1、子查询

将一条SQL语句的查询结果 “加括号” 当作另外一条SQL语句的查询条件,即为子查询;

eg:以员工表和部门表为例 >>> 查询jason所在的部门名称
步骤>>>:
    子查询
    1.先在员工表查询jason所在的部门编号;
    select dep_id from emp where name='jason';
    2.根据部门编号去部门表中查找部门名称;
    select dep_name from dep 
    where id=(select dep_id from emp where name='jason')
# 可见将子查询的结果放入查询条件可以进行使用

2、连表操作

先将多张表拼接在一起,形成一张大表,然后基于单表查询获取数据

eg:以员工表和部门表为例 >>> 查询jason所在的部门名称
步骤>>>:
    连表操作
    1.先将员工表和部门表按照某个字段拼接到一起
    2.基于单表查询

3、代码实际演练

# 数据准备
	部门表>>>:
    create table dep(
    id int primary key auto_increment,
    name varchar(32)
    );
    员工表>>>:
    create table emp(
    id int primary key auto_increment,
    name varchar(32),
    gender enum('male','female','others') default 'male',
    age int,
    dep_id int
    );
    insert into dep values(200,'技术'),(201,'人力资源'),(202,'销售'),(203,'运营'),(205,'安保');
+----+-------+--------+------+--------+
| id | name  | gender | age  | dep_id |
+----+-------+--------+------+--------+
|  1 | jason | male   |   18 |    200 |
|  2 | tony  | male   |   28 |    201 |
|  3 | oscar | male   |   38 |    201 |
|  4 | jerry | male   |   29 |    202 |
|  5 | kevin | male   |   39 |    203 |
|  6 | jack  | male   |   48 |    204 |
+----+-------+--------+------+--------+
    insert into emp(name,age,dep_id) values('jason',18,200),('tony',28,201),('oscar',38,201),('jerry',29,202),('kevin',39,203),('jack',48,204);
+-----+--------------+
| id  | name         |
+-----+--------------+
| 200 | 技术         |
| 201 | 人力资源     |
| 202 | 销售         |
| 203 | 运营         |
| 205 | 安保         |
+-----+--------------+
    
# 需求 >>>: 查询jason所在的部门名称   
	方法一:子查询
    1.先在员工表查询jason所在的部门编号;
    select dep_id from emp where name='jason';
    2.根据部门编号去部门表中查找部门名称;
    select dep_name from dep 
    where id=(select dep_id from emp where name='jason')  # 将1的结果加括号作为查询条件
    
    方法二:连表操作
    了解概念引入:(笛卡尔积)
    select * from emp,dep;  # 会将所有的数据全部对应一遍,即将部门表的每个数据都匹配给员工表的每个数据,假如员工表有6条数据,部门表有5条数据,那么会匹配成30条数据
+----+-------+--------+------+--------+-----+--------------+
| id | name  | gender | age  | dep_id | id  | name         |
+----+-------+--------+------+--------+-----+--------------+
|  1 | jason | male   |   18 |    200 | 200 | 技术         |
|  1 | jason | male   |   18 |    200 | 201 | 人力资源     |
|  1 | jason | male   |   18 |    200 | 202 | 销售         |
|  1 | jason | male   |   18 |    200 | 203 | 运营         |
|  1 | jason | male   |   18 |    200 | 205 | 安保         |
|  2 | tony  | male   |   28 |    201 | 200 | 技术         |
|  2 | tony  | male   |   28 |    201 | 201 | 人力资源     |
|  2 | tony  | male   |   28 |    201 | 202 | 销售         |
|  2 | tony  | male   |   28 |    201 | 203 | 运营         |
|  2 | tony  | male   |   28 |    201 | 205 | 安保         |
|  3 | oscar | male   |   38 |    201 | 200 | 技术         |
|  3 | oscar | male   |   38 |    201 | 201 | 人力资源     |
|  3 | oscar | male   |   38 |    201 | 202 | 销售         |
|  3 | oscar | male   |   38 |    201 | 203 | 运营         |
|  3 | oscar | male   |   38 |    201 | 205 | 安保         |
|  4 | jerry | male   |   29 |    202 | 200 | 技术         |
|  4 | jerry | male   |   29 |    202 | 201 | 人力资源     |
|  4 | jerry | male   |   29 |    202 | 202 | 销售         |
|  4 | jerry | male   |   29 |    202 | 203 | 运营         |
|  4 | jerry | male   |   29 |    202 | 205 | 安保         |
|  5 | kevin | male   |   39 |    203 | 200 | 技术         |
|  5 | kevin | male   |   39 |    203 | 201 | 人力资源     |
|  5 | kevin | male   |   39 |    203 | 202 | 销售         |
|  5 | kevin | male   |   39 |    203 | 203 | 运营         |
|  5 | kevin | male   |   39 |    203 | 205 | 安保         |
|  6 | jack  | male   |   48 |    204 | 200 | 技术         |
|  6 | jack  | male   |   48 |    204 | 201 | 人力资源     |
|  6 | jack  | male   |   48 |    204 | 202 | 销售         |
|  6 | jack  | male   |   48 |    204 | 203 | 运营         |
|  6 | jack  | male   |   48 |    204 | 205 | 安保         |
+----+-------+--------+------+--------+-----+--------------+

    可见这样是不合理的,不过我们可以加上筛选条件,如下:
    select * from emp,dep where emp.dep_id=dep.id;
+----+-------+--------+------+--------+-----+--------------+
| id | name  | gender | age  | dep_id | id  | name         |
+----+-------+--------+------+--------+-----+--------------+
|  1 | jason | male   |   18 |    200 | 200 | 技术         |
|  2 | tony  | male   |   28 |    201 | 201 | 人力资源     |
|  3 | oscar | male   |   38 |    201 | 201 | 人力资源     |
|  4 | jerry | male   |   29 |    202 | 202 | 销售         |
|  5 | kevin | male   |   39 |    203 | 203 | 运营         |
+----+-------+--------+------+--------+-----+--------------+

    但是这样效率会比较低,因此我们可以使用连表操作!
    
    连表操作(四种)>>>:
    1.inner join		内连接
    select * from emp inner join dep on emp.dep_id=dep.id;
    '''只连接两张表中有对应关系的数据'''
+----+-------+--------+------+--------+-----+--------------+
| id | name  | gender | age  | dep_id | id  | name         |
+----+-------+--------+------+--------+-----+--------------+
|  1 | jason | male   |   18 |    200 | 200 | 技术         |
|  2 | tony  | male   |   28 |    201 | 201 | 人力资源     |
|  3 | oscar | male   |   38 |    201 | 201 | 人力资源     |
|  4 | jerry | male   |   29 |    202 | 202 | 销售         |
|  5 | kevin | male   |   39 |    203 | 203 | 运营         |
+----+-------+--------+------+--------+-----+--------------+

    2.left join			左连接
  	select * from emp left join dep on emp.dep_id=dep.id;
    '''以左表为基准,展示所有的数据,没有对应项则用NULL填充'''
+----+-------+--------+------+--------+------+--------------+
| id | name  | gender | age  | dep_id | id   | name         |
+----+-------+--------+------+--------+------+--------------+
|  1 | jason | male   |   18 |    200 |  200 | 技术         |
|  2 | tony  | male   |   28 |    201 |  201 | 人力资源     |
|  3 | oscar | male   |   38 |    201 |  201 | 人力资源     |
|  4 | jerry | male   |   29 |    202 |  202 | 销售         |
|  5 | kevin | male   |   39 |    203 |  203 | 运营         |
|  6 | jack  | male   |   48 |    204 | NULL | NULL         |
+----+-------+--------+------+--------+------+--------------+
	
    3.right join		右连接
  	select * from emp right join dep on emp.dep_id=dep.id;
    '''以右表为基准 展示所有的数据 没有对应项则用NULL填充'''
+------+-------+--------+------+--------+-----+--------------+
| id   | name  | gender | age  | dep_id | id  | name         |
+------+-------+--------+------+--------+-----+--------------+
|    1 | jason | male   |   18 |    200 | 200 | 技术         |
|    2 | tony  | male   |   28 |    201 | 201 | 人力资源     |
|    3 | oscar | male   |   38 |    201 | 201 | 人力资源     |
|    4 | jerry | male   |   29 |    202 | 202 | 销售         |
|    5 | kevin | male   |   39 |    203 | 203 | 运营         |
| NULL | NULL  | NULL   | NULL |   NULL | 205 | 安保         |
+------+-------+--------+------+--------+-----+--------------+

	4.union					全连接
  	select * from emp left join dep on emp.dep_id=dep.id
    union
    select * from emp right join dep on emp.dep_id=dep.id;
    '''左右两表数据全部展示,没有对应项则用NULL填充,相当于全集'''
+------+-------+--------+------+--------+------+--------------+
| id   | name  | gender | age  | dep_id | id   | name         |
+------+-------+--------+------+--------+------+--------------+
|    1 | jason | male   |   18 |    200 |  200 | 技术         |
|    2 | tony  | male   |   28 |    201 |  201 | 人力资源     |
|    3 | oscar | male   |   38 |    201 |  201 | 人力资源     |
|    4 | jerry | male   |   29 |    202 |  202 | 销售         |
|    5 | kevin | male   |   39 |    203 |  203 | 运营         |
|    6 | jack  | male   |   48 |    204 | NULL | NULL         |
| NULL | NULL  | NULL   | NULL |   NULL |  205 | 安保         |
+------+-------+--------+------+--------+------+--------------+
    # 答案求解
    最后我们回到题目上来,查询jason所在的部门名称
    select dep.name from emp inner join dep on emp.dep_id=dep.id where emp.name='jason';
    
    
"""
总结>>>:
我们学会了连表操作之后 其实就可以将N多张表拼接到一起
	思路:我们可以将两张表拼接之后的结果起别名当做一张表使用
	然后再去跟另外一张表拼接
select * from emp inner join 
(select emp.id as epd,emp.name,dep.id from emp inner join dep on emp.dep_id=dep.id) as t1
on emp.id=t1.epd;
"""

三、可视化软件之Navicate

Navicat是一款可以操作很多数据库的软件,提供了图形化的界面窗口,方便我们更加快速地操作数据库;

1、下载

试用版下载地址:https://www.navicat.com.cn/download/navicat-premium

(1)navicat有很多版本,并且默认都是收费使用;
(2)正版可以免费体验14天 
(3)针对这种图形化软件,版本越新越好(不同版本图标颜色不一样 但是主题功能是一样的);

2、使用

使用鼠标点击的方式即可进行操作...

1.连接数据库  创建库和表 录入数据 操作数据

2.外键 
	创建表时或者右键进入设计表吗添加或修改外键
3.SQL文件 
	创建新库>>>运行SQL文件>>>导入SQL文件
4.逆向数据库到模型 
	查询表之间的关系

5.查询(自己写SQL语句)
	可以自己写SQL语句并且可以直接验证结果
    # 使用navicat编写SQL 如果自动补全语句 那么关键字都会变大写
    # SQL语句注释语法(快捷键与pycharm中的一致 ctrl+?)
    # 注释方式:
    1.#
    2.--

四、多表查询练习题

表关系如下:

mysql 使用了数据库关键字报错了怎么办_子查询

按照表的关系进行下列题目的作答

1、查询所有的课程的名称以及对应的任课老师姓名
	select course.cname,teacher.tname from course INNER JOIN teacher on course.teacher_id=teacher.tid;
4、查询平均成绩大于八十分的同学的姓名和平均成绩
	select sname,avg_num from student inner join (select student_id,avg(num) as avg_num from score group by student_id having avg_num>80 ) as a on student.sid=a.student_id;

7、查询没有报李平老师课的学生姓名
	select student.sname from student where student.sid not in (select student_id from score inner join (select cid from course inner join teacher on course.teacher_id=teacher.tid where teacher.tname='李平老师') as t1 on score.course_id=t1.cid);

8、查询没有同时选修物理课程和体育课程的学生姓名
	select sname from student where student.sid in (select student_id from score inner join (select cid from course where course.cname in ('体育','物理')) as t1 on score.course_id=t1.cid group by student_id having count(course_id)=1);

9、查询挂科超过两门(包括两门)的学生姓名和班级
	select sname,caption from student inner join class on student.class_id=class.cid where student.sid in (select student_id from score where num<60 group by student_id having count(course_id)>=2);