MySQL多表连接查询详解与实例

目录

内连接查询

等值连接查询

对连接后的查询结果,筛选、分组、排序、过滤

非等值连接查询

左连接

右连接

全外连接

嵌套查询

where之后嵌套查询

having之后嵌套查询

from之后嵌套查询(其使用效果不如内连接)

select之后嵌套查询


连接查询

                连接类型:

                          内连接:inner join

                          外联接:

                                    左外连接:left join

                                    右外连接:right join

                                    全外连接:union [all]

                连接方式:

                          交叉连接:

                          等值连接:

                          不等值连接:

  嵌套查询:

          SELECT之后

          FROM之后

          WHERE

          HAVING之后

三库之间关系

MySQL多表连接查询详解与实例_第1张图片

内连接查询

select

from                 库名.表名

inner join         库名.表名             on            连接条件

where             [表真实字段]                       分组前过滤

group by         [表真实字段]                            分组

having            [select后出现的字段]           分组后过滤

order by         [select后出现的字段]                排序

limit                      行数                                   分页

等值连接查询

查询每个员工所在的部门名

mysql> select name,dept_name
    -> from employees
    -> inner join departments     
    -> on employees.dept_id=departments.dept_id;
+-----------+-----------+
| name      | dept_name |
+-----------+-----------+
| 梁伟      | 人事部      |
| 张建平    | 财务部      |
+-----------+-----------+
    
mysql> select name,dept_name 
    -> from employees e     
    -> inner join departments d     
    -> on e.dept_id=d.dept_id;

查询员工编号8 的 员工所在部门的部门名称

mysql> select name,dept_name 
    -> from employees e     
    -> inner join departments d     
    -> on e.dept_id=d.dept_id     
    -> where e.employee_id=8;
+--------+-----------+
| name   | dept_name |
+--------+-----------+
| 汪云    | 人事部    |
+--------+-----------+
1 row in set (0.00 sec)    

对连接后的查询结果,筛选、分组、排序、过滤

查询11号员工的名字及2018年每个月总工资

mysql> select e.employee_id,name,basic,bonus,basic+bonus 月薪
    -> from salary s
    -> inner join employees e     
    -> on s.employee_id=e.employee_id
    -> where year(date)=2018 and e.employee_id=11;
+-------------+-----------+-------+-------+--------+
| employee_id | name      | basic | bonus | 月薪   |
+-------------+-----------+-------+-------+--------+
|          11 | 郭兰英    | 16206 |  2000 |  18206 |
|          11 | 郭兰英    | 16206 |  3000 |  19206 |
|          11 | 郭兰英    | 16206 |  2000 |  18206 |
|          11 | 郭兰英    | 16206 |  3000 |  19206 |
|          11 | 郭兰英    | 16206 |  2000 |  18206 |
|          11 | 郭兰英    | 16206 |  3000 |  19206 |
|          11 | 郭兰英    | 16206 | 11000 |  27206 |
|          11 | 郭兰英    | 16206 | 11000 |  27206 |
|          11 | 郭兰英    | 16206 |  3000 |  19206 |
|          11 | 郭兰英    | 16206 |  5000 |  21206 |
|          11 | 郭兰英    | 16206 |  6000 |  22206 |
|          11 | 郭兰英    | 17016 |  8000 |  25016 |
+-------------+-----------+-------+-------+--------+
12 rows in set (0.00 sec)

查询每个员工2018年的总工资

mysql> select e.employee_id,name,sum(basic+bonus) 年薪
    -> from salary s
    -> inner join employees e     
    -> on s.employee_id=e.employee_id
    -> where year(date)=2018
    -> group by s.employee_id;
+-------------+-----------+--------+
| employee_id | name      | 年薪    |
+-------------+-----------+--------+
|           1 | 梁伟      | 151046  |
|           2 | 郭岩      | 328131  |
|           3 | 李玉英    | 177595  |
+-------------+-----------+--------+

查询2018年总工资大于30万的员工,按2018年总工资降序排列

mysql> select e.employee_id,name,sum(basic+bonus) 年薪
    -> from salary s
    -> inner join employees e     
    -> on s.employee_id=e.employee_id
    -> where year(date)=2018
    -> group by s.employee_id
    -> having 年薪>300000
    -> order by 年薪 desc;
+-------------+-----------+--------+
| employee_id | name      | 年薪   |
+-------------+-----------+--------+
|         117 | 和林      | 374923  |
|          31 | 刘海燕    | 374923  |
|          37 | 朱淑兰    | 362981  |
+-------------+-----------+--------+

非等值连接查询

创建工资等级表

mysql> insert into wage_grade 
    -> values
    -> (1,'A',5000,8000),
    -> (2,'B',8001,10000),
    -> (3,'C',10001,15000),
    -> (4,'D',15001,20000),
    -> (5,'E',20001,1000000);
Query OK, 5 rows affected (0.06 sec)

mysql> select * from wage_grade;
+------+-------+-------+---------+
| id   | grade | low   | high    |
+------+-------+-------+---------+
|    1 | A     |  5000 |    8000 |
|    2 | B     |  8001 |   10000 |
|    3 | C     | 10001 |   15000 |
|    4 | D     | 15001 |   20000 |
|    5 | E     | 20001 | 1000000 |
+------+-------+-------+---------+

引入wage_grade库

MySQL多表连接查询详解与实例_第2张图片

查询2018年12月员工基本工资级别

mysql> select employee_id,date,basic,grade
    -> from salary s
    -> inner join wage_grade w 
    -> on s.basic between w.low and w.high
    -> where year(date)=2018 and month(date)=12;
+-------------+------------+-------+-------+
| employee_id | date       | basic | grade |
+-------------+------------+-------+-------+
|           1 | 2018-12-10 | 17016 | D     |
|           2 | 2018-12-10 | 20662 | E     |
|           3 | 2018-12-10 |  9724 | B     |
+-------------+------------+-------+-------+

查询2018年12月员工各基本工资级别的人数

mysql> select count(employee_id) 人数,grade 工资级别 
    -> from salary s  
    -> inner join wage_grade w 
    -> on s.basic between w.low and w.high
    -> where year(date)=2018 and month(date)=12
    -> group by grade;
+--------+--------------+
| 人数    | 工资级别      |
+--------+--------------+
|     32 | D            |
|     33 | E            |
|     12 | B            |
|     30 | C            |
|     13 | A            |
+--------+--------------+

查询2018年12月员工基本工资级别,员工需要显示姓名

mysql> select e.name,s.date,s.basic,w.grade
    -> from salary s
    -> inner join wage_grade w
    -> on s.basic BETWEEN w.low AND w.high
    -> inner join employees e
    -> on e.employee_id=s.employee_id
    -> where year(date)=2018 and month(date)=12;
+-----------+------------+-------+-------+
| name      | date       | basic | grade |
+-----------+------------+-------+-------+
| 梁伟      | 2018-12-10 | 17016 | D     |
| 郭岩      | 2018-12-10 | 20662 | E     |
| 李玉英    | 2018-12-10 |  9724 | B      |
+-----------+------------+-------+-------+

左连接

以left join左边的表为主表

向departments表里添加3个部门:小卖部 行政部 公关部

mysql> insert into departments(dept_name) 
    -> values("小卖部"),("行政部"),("公关部");

输出没有员工的部门名

mysql> select d.dept_name,e.name
    -> from departments d
    -> left join employees e
    -> on d.dept_id=e.dept_id
    -> where e.name is null;
+-----------+------+
| dept_name | name |
+-----------+------+
| 小卖部    | NULL  |
| 行政部    | NULL  |
| 公关部    | NULL  |
+-----------+------+
3 rows in set (0.00 sec)

#若两张表位置互换
mysql> select d.dept_name,e.name
    -> from employees e
    -> left join departments d
    -> on d.dept_id=e.dept_id
    -> where e.name is null;
Empty set (0.00 sec)

右连接

以right join右边的表为主表

mysql> select d.dept_name,e.name
    -> from employees e
    -> right join departments d
    -> on d.dept_id=e.dept_id
    -> where e.name is null;
+-----------+------+
| dept_name | name |
+-----------+------+
| 小卖部    | NULL  |
| 行政部    | NULL  |
| 公关部    | NULL  |
+-----------+------+
3 rows in set (0.00 sec)

全外连接

union:自动去重

union all:拼接全部

mysql> (select d.dept_name,e.name 
    -> FROM departments d 
    -> LEFT JOIN employees e     
    -> on d.dept_id=e.dept_id)
    -> UNION
    -> (select d.dept_name,e.name 
    -> FROM departments d 
    -> RIGHT JOIN employees e     
    -> on d.dept_id=e.dept_id);

mysql> (select d.dept_name,e.name     
    -> FROM departments d 
    -> LEFT JOIN employees e     
    -> on d.dept_id=e.dept_id)
    -> UNION ALL
    -> (select d.dept_name,e.name     
    -> FROM departments d 
    -> RIGHT JOIN employees e     
    -> on d.dept_id=e.dept_id);
    
mysql> (select d.dept_name,e.name 
    ->  FROM departments d  
    ->  LEFT JOIN employees e 
    ->  on d.dept_id=e.dept_id
    -> where d.dept_name is null or e.name is null) 
    -> UNION 
    -> (select d.dept_name,e.name 
    ->  FROM departments d  
    ->  RIGHT JOIN employees e 
    ->  on d.dept_id=e.dept_id
    -> where d.dept_name is null or e.name is null);
+-----------+------+
| dept_name | name |
+-----------+------+
| 小卖部    | NULL |
| 行政部    | NULL |
| 公关部    | NULL |
| NULL     | bob  |
| NULL     | tom  |
| NULL     | lily |
+-----------+------+

嵌套查询

在一个完整的查询语句之中,包含若干个不同功能的小查询;从而一起完成复杂查询的一种编写形式。包含的查询放在()里 , 包含的查询出现的位置

where之后嵌套查询

查询运维部所有员工信息

mysql> select * from employees
    -> where employees.dept_id=(
    -> SELECT dept_id 
    -> from departments
    -> where departments.dept_name='运维部');
+-------------+-----------+------------+------------+--------------------+--------------+---------+
| employee_id | name      | hire_date  | birth_date | email              | phone_number | dept_id |
+-------------+-----------+------------+------------+--------------------+--------------+---------+
|          14 | 廖娜      | 2012-05-20 | 1982-06-22 | [email protected]  | 15827928192  |       3 |
|          15 | 窦红梅    | 2018-03-16 | 1971-09-09 | [email protected] | 15004739483  |       3 |
|          16 | 聂想      | 2018-09-09 | 1999-06-05 | [email protected]   | 15501892446  |       3 |
|          17 | 陈阳      | 2004-09-16 | 1991-04-10 | [email protected]   | 15565662056  |       3 |
|          18 | 戴璐      | 2001-11-30 | 1975-05-16 | [email protected]      | 13465236095  |       3 |
|          19 | 陈斌      | 2019-07-04 | 2000-01-22 | [email protected] | 13621656037  |       3 |
+-------------+-----------+------------+------------+--------------------+--------------+---------+

查询人事部2018年12月所有员工工资

mysql> select *
    -> FROM salary s
    -> where year(date)=2018 and month(date)=12 and employee_id in (select employee_id
    -> from employees e 
    -> where e.dept_id=(select dept_id
    -> from departments d 
    -> where d.dept_name='人事部'));
+------+------------+-------------+-------+-------+
| id   | date       | employee_id | basic | bonus |
+------+------------+-------------+-------+-------+
| 6252 | 2018-12-10 |           1 | 17016 |  7000 |
| 6253 | 2018-12-10 |           2 | 20662 |  9000 |
| 6254 | 2018-12-10 |           3 |  9724 |  8000 |
| 6255 | 2018-12-10 |           4 | 17016 |  2000 |
| 6256 | 2018-12-10 |           5 | 17016 |  3000 |
| 6257 | 2018-12-10 |           6 | 17016 |  1000 |
| 6258 | 2018-12-10 |           7 | 23093 |  4000 |
| 6259 | 2018-12-10 |           8 | 23093 |  2000 |
+------+------------+-------------+-------+-------+

查询2018年12月所有比100号员工基本工资高的工资信息

mysql> select basic
    -> from salary
    -> where year(date)=2018 and month(date)=12 and basic>(
    -> select basic
    -> from salary
    -> where year(date)=2018 and month(date)=12 and employee_id=100)
    -> order by basic desc;
+-------+
| basic |
+-------+
| 25524 |
| 25524 |
| 25524 |
+-------+

having之后嵌套查询

查询部门员工总人数比开发部总人数少的部门名称和人数

mysql> select dept_id,COUNT(employee_id) total 
    -> from employees
    -> group by dept_id
    -> having total < (select count(employee_id)
    -> from employees
    -> where employees.dept_id=(
    -> select dept_id 
    -> from departments
    -> where departments.dept_name='开发部'));
+---------+-------+
| dept_id | total |
+---------+-------+
|    NULL |     3 |
|       1 |     8 |
|       2 |     5 |
|       3 |     6 |
|       5 |    12 |
|       6 |     9 |
|       7 |    35 |
|       8 |     3 |
+---------+-------+

from之后嵌套查询(其使用效果不如内连接)

查询3号部门 、部门名称 及其部门内 员工的编号、名字 和 email

mysql> select dept_id,dept_name,name,email 
    -> from (select d.dept_name,e.* 
    -> from departments d
    -> INNER JOIN employees e 
    -> on d.dept_id=e.dept_id) tmp_tabel
    -> where dept_id=3;
+---------+-----------+-----------+--------------------+
| dept_id | dept_name | name      | email              |
+---------+-----------+-----------+--------------------+
|       3 | 运维部    | 廖娜      | [email protected]  |
|       3 | 运维部    | 窦红梅    | [email protected] |
|       3 | 运维部    | 聂想      | [email protected]   |
|       3 | 运维部    | 陈阳      | [email protected]   |
|       3 | 运维部    | 戴璐      | [email protected]      |
|       3 | 运维部    | 陈斌      | [email protected] |
+---------+-----------+-----------+--------------------+

select之后嵌套查询

查询每个部门的人数

mysql> select d.dept_id,d.dept_name,(
    -> select count(*) 
    ->     from employees e
    ->     where d.dept_id=e.dept_id
    -> ) cnt
    -> from departments d;
+---------+-----------+------+
| dept_id | dept_name | cnt  |
+---------+-----------+------+
|       1 | 人事部    |    8 |
|       2 | 财务部    |    5 |
|       3 | 运维部    |    6 |
|       4 | 开发部    |   55 |
|       5 | 测试部    |   12 |
|       6 | 市场部    |    9 |
|       7 | 销售部    |   35 |
|       8 | 法务部    |    3 |
|       9 | 小卖部    |    0 |
|      10 | 行政部    |    0 |
|      11 | 公关部    |    0 |
+---------+-----------+------+

你可能感兴趣的:(mysql,数据库,linux,sql)