MySQL数据库(4)- 多表查询、可视化工具Navicat的使用、设计模式MVC

时间:2024-03-01 18:07:21

一、多表查询

       准备工作:创建两张表,部门表(department)、员工表(employee),代码和表格如下:

# 创建表
create table department(
    id int,
    name varchar(20) 
);
create table employee(
    id int primary key auto_increment,
    name varchar(20),
    gender enum(\'male\',\'female\') not null default \'male\',
    age int,
    dep_id int
);

# 插入数据
insert into department values
(200,\'技术\'),
(201,\'人力资源\'),
(202,\'销售\'),
(203,\'运营\');

insert into employee(name,gender,age,dep_id) values
(\'egon\',\'male\',18,200),
(\'alex\',\'female\',48,201),
(\'wupeiqi\',\'male\',38,201),
(\'yuanhao\',\'female\',28,202),
(\'nvshen\',\'male\',18,200),
(\'xiaomage\',\'female\',18,204);
代码

id

name

 

id

name

gender

age

dep_id

200

技术

 

1

egon

male

18

200

201

人力资源

 

2

alex

female

48

201

202

销售

 

3

wupeiqi

male

38

201

203

运营

 

4

yuanhao

female

28

202

 

 

5

nvshen

male

18

200

 

6

xiaomage

female

18

204

       PS:观察两张表,可以发现,department表中id=203部门没有对应的员工,employee表中id=6的员工没有对应的部门。

1、多表连接查询

       两张表的准备工作已经完成,比如现在我要查询某员工信息以及该员工所在的部门,就要将两张表进行连接查询,多表连接查询,有以下几种情况:

       a、交叉连接:不适用任何匹配条件,生成笛卡尔积

    mysql> select * from employee,department;

       b、外链接之内连接:只连接匹配的行    

  # 找出两张表共有的部分
  # department表中没有204这个部门,employee表中也没有运营部的员工,因此没有显示
  mysql> select * from employee inner join department on employee.dep_id=department.id;
  +----+---------+--------+------+--------+------+--------------+
  | id | name    | gender | age  | dep_id | id   | name         |
  +----+---------+--------+------+--------+------+--------------+
  |  1 | egon    | male   |  18  |   200  |  200 | 技术          |
  |  2 | alex    | female |   48 |   201  |  201 | 人力资源      |
  |  3 | wupeiqi | male   |  38  |    201 |  201 | 人力资源      |
  |  4 | yuanhao | female |  28  |    202 |  202 | 销售          |
  |  5 |  nvshen | male   |  18  |   200  |  200 | 技术          |
  +----+---------+--------+------+--------+------+--------------+
  5 rows in set (0.00 sec)  
  # 上述sql查询语句等同于
  mysql> select * from employee,department where employee.dep_id=department.id;

       c、外链接之左连接:优先显示左表全部记录 

  # 以左表(employee表)为准,即找出所有员工信息,当然包括没有部门的员工
  # 本质:在内连接的基础上增加左表有,右表没有的结果
  mysql> select employee.id,employee.name,department.name as depart_name
  from employee left join department 
  on employee.dep_id=department.id;
  +----+----------+--------------+
  | id | name     | depart_name  |
  +----+----------+--------------+
  |  1 | egon     | 技术          |
  |  5 | nvshen   | 技术          |
  |  2 | alex     | 人力资源      |
  |  3 | wupeiqi  | 人力资源      |
  |  4 | yuanhao  | 销售          |
  |  6 | xiaomage | NULL         |
  +----+----------+--------------+

       d、外链接之右连接:优先显示右表全部记录    

  # 以右表(department表)为准,即找出所有部门信息,包括没有员工的部门
  # 本质:在内连接的基础上增加右表有,左表没有的结果
  mysql> select employee.id,employee.name,department.name as depart_name
  from employee right join department 
  on employee.dep_id=department.id;
  +------+---------+--------------+
  | id   | name    | depart_name  |
  +------+---------+--------------+
  |    1 | egon    | 技术         |
  |    2 | alex    | 人力资源      |
  |    3 | wupeiqi | 人力资源      |
  |    4 | yuanhao | 销售         |
  |    5 | nvshen  | 技术         |
  | NULL | NULL    | 运营         |
  +------+---------+--------------+

       e、全外连接:显示左右两个表的全部记录(了解)

              在内连接的基础上增加左表有、右表没有的和左表没有、右表有的结果

              注意:MySQL不支持full join的全外连接,但可以用union/union all间接实现全外连接 

  mysql> select * from employee left join department 
    on employee.dep_id = department.id
    union
    select * from employee right join department 
    on employee.dep_id = department.id;
  +------+----------+-----------+--------+----------+--------+-----------+
  | id  | name   | gender | age  | dep_id | id   | name     |
  +------+-------+-------+------+--------+------+---------+
  |    1 | egon   | male   |   18 |    200 |  200 | 技术       |
  |    5 | nvshen | male   |   18 |    200 |  200 | 技术       |
  |    2 | alex   | female |   48 |    201 |  201 | 人力资源    |
  |    3 | wupeiqi| male   |   38 |    201 |  201 | 人力资源    |
  |    4 | yuanhao| female |   28 |    202 |  202 | 销售        |
  |    6 | xiaomage| female|   18 |    204 | NULL | NULL       |
  | NULL| NULL     | NULL  | NULL |   NULL |  203 | 运营        |
  +------+----------+--------+------+--------+------+--------+
  7 rows in set (0.01 sec)
  mysql> select * from employee left join department 
    on employee.dep_id = department.id
    union all
    select * from employee right join department 
    on employee.dep_id = department.id;

              总结: union与union all的区别:union会去掉相同的纪录。

2、符合条件连接查询

       示例一:以内连接的方式查询employee和department表,并且employee表中的age字段值必须大于25,即找出年龄大于25岁的员工以及员工所在的部门

    mysql> select employee.name,department.name 
       from employee inner join department
       on employee.dep_id = department.id where age > 25;

       示例二:以内连接的方式查询employee和department表,并且以age字段的升序方式显示

    mysql> select employee.id,employee.name,employee.age,department.name 
       from employee inner join department
       on employee.dep_id = department.id and age > 25
       order by age asc;
3、子查询

       1)子查询是将一个查询语句嵌套在另一个查询语句中;

       2)内层查询语句的查询结果,可以为外层查询语句提供查询条件;

       3)子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS和NOT EXISTS等关键字;

       4)还可以包含比较运算符:>、<、=、>=、<=、!=等;

       示例一:带IN/NOT IN关键字的子查询

    # 查询平均年龄在25岁以上的部门名
  mysql> select id,name from department where id in
    (select dep_id from employee group by dep_id having avg(age) > 25);

  # 查看技术部员工姓名
  mysql> select name from employee where dep_id in 
       (select id from department where name = \'技术\');

  # 查看不足1人的部门名
  mysql> select name from department where id not in 
    (select dep_id from employee group by dep_id);

       示例二:带比较运算符的子查询

    # 查询大于所有人平均年龄的员工名与年龄
  mysql> select name,age from employee where age > (select avg(age) from employee);

  # 查询大于部门内平均年龄的员工名、年龄
  mysql> select t1.name,t1.age from employee as t1
    inner join
    (select dep_id,avg(age) as avg_age from employee group by dep_id) as t2
    on t1.dep_id = t2.dep_id
    where t1.age > t2.avg_age;

       示例三:带EXISTS关键字的子查询

       EXISTS关字键字表示存在。在使用EXISTS关键字时,内层查询语句不返回查询的记录。而是返回一个真假值,True或False。

       当返回True时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询。

  # department表中存在id=203,返回Ture
  mysql> select * from employee where exists (select id from department where id=203);
  +----+----------+--------+------+--------+
  | id | name     | gender | age  | dep_id |
  +----+----------+--------+------+--------+
  |  1 | egon     | male   |   18 |    200 |
  |  2 | alex     | female |   48 |    201 |
  |  3 | wupeiqi  | male   |   38 |    201 |
  |  4 | yuanhao  | female |   28 |    202 |
  |  5 | nvshen   | male   |   18 |    200 |
  |  6 | xiaomage | female |   18 |    204 |
  +----+----------+--------+------+--------+

  # department表中不存在id=204,返回False
  mysql> select * from employee where exists (select id from department where id=204);
  Empty set (0.00 sec)

二、可视化工具Navicat的使用

       在生产环境中操作MySQL数据库还是推荐使用命令行工具,但在我们自己开发测试时,可以使用可视化工具Navicat,以图形界面的形式操作MySQL数据库。

       官网下载:https://www.navicat.com/en/products/navicat-for-mysql

       网盘下载:https://pan.baidu.com/s/1bpo5mqj

       需要掌握基本的操作:

              1)测试 + 链接数据库

              2)新建库

              3)新建表,新增字段 + 类型 + 约束

              4)设计表:外键

              5)新建查询

              6)备份库/表

       PS:

    批量加注释:ctrl + /
    批量去注释:ctrl + shift + /

三、设计模式MVC

       MVC模式代表Model-Viewl-Controller(模型-视图-控制器)模式。用于应用程序的分层开发。

              Model(模型) - 模型代表一个存取数据的对象或 JAVA POJO。它也可以带有逻辑,在数据变化时更新控制器;

              View(视图) - 视图代表模型包含的数据的可视化;

              Controller(控制器) - 控制器作用于模型和视图上,它控制数据流向模型对象,并在数据变化时更新视图。它使视图与模型分离开;