前言

简单的数据我们可以直接从一个表中获取,但在真实的项目中查询符合条件的数据通常需要牵扯到多张表,这就不得不使用多表查询。多表查询分为多表连接查询、符合条件链接查询、子查询。多表连接查询包括内连接、外连接、全连接。符合条件连接查询本质上是多表连接查询+过滤条件。子查询是将一个查询语句嵌套在另一个查询语句中,内层查询语句的查询结果作为外层查询语句的数据源。

准备

# 建表

create table department(

id int,

name varchar(20)

);

create table employee(

id int primary key auto_increment,

name varchar(20),

sex enum('male','female') not null default 'male',

age int,

dep_id int

);

# 插入数据

insert into department values

(1,'技术'),

(2,'财务'),

(3,'法律’);

# 此处省略员工表数据...

多表连接查询

语法

SELECT 字段列表

FROM 表1 INNER|LEFT|RIGHT JOIN 表2

ON 表1.字段 = 表2.字段;

交叉连接

在介绍多表查询的时候,有必要先介绍下交叉连接,如下select * from employee, department;查询语句就是交叉连接查询,可以看出,同一个数据在在employee表和department表交叉连接之后产生了重复记录,其重复个数取决于department表的记录个数。所以最后交叉连接之后的记录个数是:count(employee) * count(department),即笛卡尔积。通常情况下,笛卡尔积的结果在工作中无实际意义,我们需要在笛卡尔积的基础上进行筛选,找到employee.dep_id = department.id的那条记录。

mysql> select * from employee, department;

+----+-------+------+--------+----------+-----------+--------+------+--------+

| id | name | age | sex | position | salary | dep_id | id | name |

+----+-------+------+--------+----------+-----------+--------+------+--------+

| 1 | jack | 20 | male | lawyer | 888889 | 3 | 1 | 技术 |

| 1 | jack | 20 | male | lawyer | 888889 | 3 | 2 | 财务 |

| 1 | jack | 20 | male | lawyer | 888889 | 3 | 3 | 法律 |

| 2 | mark | 22 | male | lawyer | 888889 | 3 | 1 | 技术 |

| 2 | mark | 22 | male | lawyer | 888889 | 3 | 2 | 财务 |

| 2 | mark | 22 | male | lawyer | 888889 | 3 | 3 | 法律 |

| 3 | hank | 25 | male | lawyer | 7777.8 | 3 | 1 | 技术 |

| 3 | hank | 25 | male | lawyer | 7777.8 | 3 | 2 | 财务 |

| 3 | hank | 25 | male | lawyer | 7777.8 | 3 | 3 | 法律 |

| 4 | nick | 39 | male | lawyer | 4438890 | 3 | 1 | 技术 |

| 4 | nick | 39 | male | lawyer | 4438890 | 3 | 2 | 财务 |

| 4 | nick | 39 | male | lawyer | 4438890 | 3 | 3 | 法律 |

| 5 | jenny | 26 | female | lawyer | 10000.8 | 3 | 1 | 技术 |

| 5 | jenny | 26 | female | lawyer | 10000.8 | 3 | 2 | 财务 |

| 5 | jenny | 26 | female | lawyer | 10000.8 | 3 | 3 | 法律 |

| 6 | tony | 35 | male | RD | 100000000 | 1 | 1 | 技术 |

| 6 | tony | 35 | male | RD | 100000000 | 1 | 2 | 财务 |

| 6 | tony | 35 | male | RD | 100000000 | 1 | 3 | 法律 |

| 7 | emmy | 27 | female | RD | 9999 | 1 | 1 | 技术 |

| 7 | emmy | 27 | female | RD | 9999 | 1 | 2 | 财务 |

| 7 | emmy | 27 | female | RD | 9999 | 1 | 3 | 法律 |

| 8 | emmy | 23 | female | finance | 5000 | 2 | 1 | 技术 |

| 8 | emmy | 23 | female | finance | 5000 | 2 | 2 | 财务 |

| 8 | emmy | 23 | female | finance | 5000 | 2 | 3 | 法律 |

| 9 | lucy | 45 | female | finance | 10000 | 2 | 1 | 技术 |

| 9 | lucy | 45 | female | finance | 10000 | 2 | 2 | 财务 |

| 9 | lucy | 45 | female | finance | 10000 | 2 | 3 | 法律 |

| 10 | emmi | 20 | female | finance | 20000 | 2 | 1 | 技术 |

| 10 | emmi | 20 | female | finance | 20000 | 2 | 2 | 财务 |

| 10 | emmi | 20 | female | finance | 20000 | 2 | 3 | 法律 |

| 11 | james | 18 | male | NULL | 3000 | NULL | 1 | 技术 |

| 11 | james | 18 | male | NULL | 3000 | NULL | 2 | 财务 |

| 11 | james | 18 | male | NULL | 3000 | NULL | 3 | 法律 |

+----+-------+------+--------+----------+-----------+--------+------+--------+

33 rows in set (0.00 sec)

内连接

内连接只会连接两张表匹配的行,即取交集。找两张表公共部分,相当于利用条件从笛卡尔积结果中筛选出了正确的结果

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

+----+-------+------+--------+--------+

| id | name | age | sex | name |

+----+-------+------+--------+--------+

| 1 | jack | 20 | male | 法律 |

| 2 | mark | 22 | male | 法律 |

| 3 | hank | 25 | male | 法律 |

| 4 | nick | 39 | male | 法律 |

| 5 | jenny | 26 | female | 法律 |

| 6 | tony | 35 | male | 技术 |

| 7 | emmy | 27 | female | 技术 |

| 8 | emmy | 23 | female | 财务 |

| 9 | lucy | 45 | female | 财务 |

| 10 | emmi | 20 | female | 财务 |

+----+-------+------+--------+--------+

10 rows in set (0.00 sec)

上述内连接查询语句等同于:

mysql> select employee.id,employee.name,employee.age,employee.sex,department.name

from employee,department

where employee.dep_id=department.id;

外连接

外连接分为左连接、右连接、全外连接

左连接

左连接在内连接的基础上优先显示左表全部记录。即左连接=内连接+左表未符合条件的记录

#以左表为准,即找出所有员工信息,当然包括没有部门的员工

#本质就是:在内连接的基础上增加左边有右边没有的结果

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 |

+----+-------+-------------+

| 6 | tony | 技术 |

| 7 | emmy | 技术 |

| 8 | emmy | 财务 |

| 9 | lucy | 财务 |

| 10 | emmi | 财务 |

| 1 | jack | 法律 |

| 2 | mark | 法律 |

| 3 | hank | 法律 |

| 4 | nick | 法律 |

| 5 | jenny | 法律 |

| 11 | james | NULL |

+----+-------+-------------+

11 rows in set (0.00 sec)

右连接

又连接在内连接的基础上优先显示右表的内容。即右连接==内连接+右表未符合条件的记录

#以右表为准,即找出所有部门信息,包括没有员工的部门

#本质就是:在内连接的基础上增加右边有左边没有的结果

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 | jack | 法律 |

| 2 | mark | 法律 |

| 3 | hank | 法律 |

| 4 | nick | 法律 |

| 5 | jenny | 法律 |

| 6 | tony | 技术 |

| 7 | emmy | 技术 |

| 8 | emmy | 财务 |

| 9 | lucy | 财务 |

| 10 | emmi | 财务 |

+------+-------+-------------+

10 rows in set (0.00 sec)

可以发现,左表(employee表)的第11条记录没有被查询出来

全外连接

全外连接会在内连接查询的基础上显示左表和右表的全部记录

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 | age | sex | position | salary | dep_id | id | name |

+------+-------+------+--------+----------+-----------+--------+------+--------+

| 6 | tony | 35 | male | RD | 100000000 | 1 | 1 | 技术 |

| 7 | emmy | 27 | female | RD | 9999 | 1 | 1 | 技术 |

| 8 | emmy | 23 | female | finance | 5000 | 2 | 2 | 财务 |

| 9 | lucy | 45 | female | finance | 10000 | 2 | 2 | 财务 |

| 10 | emmi | 20 | female | finance | 20000 | 2 | 2 | 财务 |

| 1 | jack | 20 | male | lawyer | 888889 | 3 | 3 | 法律 |

| 2 | mark | 22 | male | lawyer | 888889 | 3 | 3 | 法律 |

| 3 | hank | 25 | male | lawyer | 7777.8 | 3 | 3 | 法律 |

| 4 | nick | 39 | male | lawyer | 4438890 | 3 | 3 | 法律 |

| 5 | jenny | 26 | female | lawyer | 10000.8 | 3 | 3 | 法律 |

| 11 | james | 18 | male | NULL | 3000 | NULL | NULL | NULL |

| NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | 人力 |

+------+-------+------+--------+----------+-----------+--------+------+--------+

12 rows in set (0.00 sec)

符合条件链接查询

mysql> select employee.name, employee.age, department.name from employee inner join department

-> on employee.dep_id=department.id

-> where age > 30

-> order by age asc;

+------+------+--------+

| name | age | name |

+------+------+--------+

| tony | 35 | 技术 |

| nick | 39 | 法律 |

| lucy | 45 | 财务 |

+------+------+--------+

3 rows in set (0.00 sec)

子查询

子查询是将一个查询语句的嵌套在另一个查询语句中

内层查询语句的查询结果作为外层查询语句的数据源

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

注意被嵌套的查询语句需要用( )包裹

查询员工部门平均年龄大于30的部门信息

mysql> select * from department

-> where id in

-> (select dep_id from employee group by dep_id having avg(age) > 30);

+------+--------+

| id | name |

+------+--------+

| 1 | 技术 |

+------+--------+

1 row in set (0.00 sec)

查询技术部员工姓名

mysql> select name from employee

-> where dep_id in

-> (select id from department where name="技术");

+------+

| name |

+------+

| tony |

| emmy |

+------+

2 rows in set (0.00 sec)

查询无员工的部门名(子查询得到的是所有人的部门id,需要disctinct去除)

mysql> select name from department

-> where id not in

-> (select distinct dep_id from employee);

带比较运算符的子查询

查询大于所有人平均年龄的员工名和年龄

mysql> select * from employee where age > (select avg(age) from employee);

+----+------+------+--------+----------+-----------+--------+

| id | name | age | sex | position | salary | dep_id |

+----+------+------+--------+----------+-----------+--------+

| 4 | nick | 39 | male | lawyer | 4438890 | 3 |

| 6 | tony | 35 | male | RD | 100000000 | 1 |

| 9 | lucy | 45 | female | finance | 10000 | 2 |

+----+------+------+--------+----------+-----------+--------+

3 rows in set (0.00 sec)

不能这样:在前面没有group by的时后面不能使用分组函数

mysql> select * from employee where age > avg(age);

ERROR 1111 (HY000): Invalid use of group function

带EXISTS关键字的子查询

EXISTS关字键字表示存在。在使用EXISTS关键字时,内层查询语句不返回查询的记录。

而是返回一个真假值。True或False

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

mysql> select * from employee

-> where exists

-> (select id from department where id=200);

MYSQL中可以把一个查询语句用括号括起来使用as起一个别名当做一个表使用

查询每个职位最新入职的员工

SELECT

*

FROM

emp AS t1

INNER JOIN (

SELECT

post,

max(hire_date) max_date

FROM

emp

GROUP BY

post

) AS t2 ON t1.post = t2.post

WHERE

t1.hire_date = t2.max_date;

查询语句关键字执行顺序

一个完整的mysql的查询语句如下:

SELECT DISTINCT

FROM

JOIN

ON

WHERE

GROUP BY

HAVING

ORDER BY

LIMIT

其关键字执行顺序如下:

(7) SELECT

(8) DISTINCT

(1) FROM

(3) JOIN

(2) ON

(4) WHERE

(5) GROUP BY

(6) HAVING

(9) ORDER BY

(10) LIMIT

MySQL 后from多个表_MYSQL回顾(多表查询相关)相关推荐

  1. mysql存储引擎静态表_MySQL存储引擎(表类型)的选择

    一.MySQL存储引擎概述 MySQL与多数数据库不同的是包含存储引擎这一特性,用户可以根据应用的需要选择合适的存储引擎来使存储和索引数据,以及是否使用事务等.MySQL5.0支持的存储引擎包括MyI ...

  2. mysql 主从单表_MySQL主从复制单表或者多表

    MySQL数据库安装不过多的介绍了:必须保证2个数据库的版本一致. 主数据库:192.168.0.43 从数据库:192.168.0.53 修改43主数据库的配置文件: 打开logbin日志生成文件: ...

  3. mysql简单分表_mysql分区分表哪个好

    一,什么是e69da5e6ba9062616964757a686964616f31333365633933mysql分表,分区 什么是分表,从表面意思上看呢,就是把一张表分成N多个小表,具体请看mys ...

  4. mysql单源多表同步单库单表_MySQL主从复制单表或者多表

    MySQL数据库安装不过多的介绍了:必须保证2个数据库的版本一致. 主数据库:192.168.0.43 从数据库:192.168.0.53 修改43主数据 MySQL数据库安装不过多的介绍了:必须保证 ...

  5. mysql连接多个存储存储_Mysql(三):多表查询和存储程序

    今天内容: ● 多表查询(内连接 外连接 子查询) ● 存储程序(存储过程 函数) 多表查询 ​同时从多张数据表中查取到需要的数据即是多表查询. 多表查询时,参与查询的表中每条数据进行组合,这种效果称 ...

  6. mysql 创建删除表_mysql创建删除表的的详细解析

    本文主要介绍MySQL.html "target =" _ blank "> MySQL对创建删除表的详细分析.我希望作者收集的相关知识和数据对你有所帮助.创建 表 ...

  7. mysql数据库操作宠物表_mysql数据库及表的基本操作

    1. 数据库操作 1.1 创建数据库 # 创建数据库 mysql> create database db_test; # 查看创建好的数据库 mysql> show create data ...

  8. mysql 存储过程建表_MySQL 存储过程创建表

    创建 CREATE PROCEDURE  Pro_IsExistTable(ableName varchar(100),out outputParam int) BEGIN set @csql=con ...

  9. mysql创建销售表_MySQL创建数据表(CREATE TABLE语句)

    在创建数据库之后,接下来就要在数据库中创建数据表.所谓创建数据表,指的是在已经创建的数据库中建立新表. 创建数据表的过程是规定数据列的属性的过程,同时也是实施数据完整性(包括实体完整性.引用完整性和域 ...

  10. mysql重新命名表_MySQL重命名表

    在本教程中,您将学习如何使用MySQL RENAME TABLE语句和ALTER TABLE语句重命名表. MySQL RENAME TABLE语句简介 由于业务需求变化,我们需要将当前表重新命名为新 ...

最新文章

  1. WebKit与event.layerX和event.layerY有关的问题
  2. WinForms多线程编程之多线程计算器
  3. pat天梯赛L1-054. 福到了
  4. 一文总结 CPU 基本知识
  5. TCP协议以及三次握手
  6. mysql语言的创建模式文件_南开17春学期《数据库应用系统设计》在线作业 免费答案...
  7. 据说有人面试栽在了Thread类的stop()方法和interrupt()方法上
  8. MS OFFICE在LINUX上的视觉效果跟WINDOWS相差太大
  9. 【生信进阶练习1000days】day14-GenomicDataCommons(GDC)
  10. undefined reference to错误的解决方法
  11. AEJoy —— 表达式之通过 sampleImage() 营造遮蔽效果【JS】
  12. Shopee数据获取逻辑
  13. Ci522 13.56MHz非接触式读写器芯片--Si522 Lowcost版本
  14. 魔百盒CM211-1-晶晨S905L3B芯片系列-红外蓝牙线刷固件及教程
  15. 深海油气开发利器——水下机器人
  16. Python OpenSSL基本操作接口
  17. 常用桌面端软件开发语言整理
  18. LOOP AT SCREEN ABAP
  19. 百度财报解析-百度云要变成老大哥
  20. 【Fiddler介绍】

热门文章

  1. AUTOSAR从入门到精通100讲(十三)-autosar架构中的ASPICE模块
  2. 子集和问题 算法_子集问题 主要是去重算法
  3. linux多进程 段错误,关于段错误
  4. idea 导出war包_使用IDEA实现远程代码DEBUG调试教程详解
  5. 有var d = new Date(‘20xx-m-09‘),可以设置为m+1月份的操作是?
  6. Android killer软件闪退的解决办法?
  7. $.fn.zTree 展开 回显 选中
  8. 微信内置浏览器点击“返回”关闭窗口
  9. vue父组件向子组件动态传值的两种方法
  10. 让Vue也可以使用Redux