FOREIGN MySQL 之 多表查询
一.多表联合查询
#创建部门
CREATE TABLE IF NOT EXISTS dept (
did int not null auto_increment PRIMARY KEY,
dname VARCHAR(50) not null COMMENT '部门名称'
)ENGINE=INNODB DEFAULT charset utf8; #添加部门数据
INSERT INTO `dept` VALUES ('', '教学部');
INSERT INTO `dept` VALUES ('', '销售部');
INSERT INTO `dept` VALUES ('', '市场部');
INSERT INTO `dept` VALUES ('', '人事部');
INSERT INTO `dept` VALUES ('', '鼓励部'); -- 创建人员
DROP TABLE IF EXISTS `person`;
CREATE TABLE `person` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`age` tinyint(4) DEFAULT '',
`sex` enum('男','女','人妖') NOT NULL DEFAULT '人妖',
`salary` decimal(10,2) NOT NULL DEFAULT '250.00',
`hire_date` date NOT NULL,
`did` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8; -- 添加人员数据 -- 教学部
INSERT INTO `person` VALUES ('', 'alex', '', '人妖', '53000.00', '2010-06-21', '');
INSERT INTO `person` VALUES ('', 'wupeiqi', '', '男', '8000.00', '2011-02-21', '');
INSERT INTO `person` VALUES ('', 'egon', '', '男', '6500.00', '2015-06-21', '');
INSERT INTO `person` VALUES ('', 'jingnvshen', '', '女', '6680.00', '2014-06-21', ''); -- 销售部
INSERT INTO `person` VALUES ('', '歪歪', '', '女', '3000.00', '2015-02-21', '');
INSERT INTO `person` VALUES ('', '星星', '', '女', '2000.00', '2018-01-30', '');
INSERT INTO `person` VALUES ('', '格格', '', '女', '2000.00', '2018-02-27', '');
INSERT INTO `person` VALUES ('', '周周', '', '女', '2000.00', '2015-06-21', ''); -- 市场部
INSERT INTO `person` VALUES ('', '月月', '', '女', '4000.00', '2014-07-21', '');
INSERT INTO `person` VALUES ('', '安琪', '', '女', '4000.00', '2015-07-15', ''); -- 人事部
INSERT INTO `person` VALUES ('', '周明月', '', '女', '5000.00', '2014-06-21', ''); -- 鼓励部
INSERT INTO `person` VALUES ('', '苍老师', '', '女', '1000000.00', '2018-02-21', null);
创建表和数据
1
2
|
#多表查询语法 select 字段1,字段2... from 表1,表2... [ where 条件] |
注意: 如果不加条件直接进行查询,则会出现以下效果,这种结果我们称之为 笛卡尔乘积
1
2
|
#查询人员和部门所有信息 select * from person,dept |
笛卡尔乘积公式 : A表中数据条数 * B表中数据条数 = 笛卡尔乘积.
select * from person ,dept;
笛卡尔乘积示例
1
2
3
4
|
#查询人员和部门所有信息 select * from person,dept where person.dept_id = dept.did; #注意: 多表查询时,一定要找到两个表中相互关联的字段,并且作为条件使用 |
select * from person,dept where person.did = dept.did;
二 多表连接查询
1
2
3
4
|
#多表连接查询语法(重点) SELECT 字段列表 FROM 表1 INNER | LEFT | RIGHT JOIN 表2 ON 表1.字段 = 表2.字段; |
1 内连接查询 (只显示符合条件的数据)
1
2
|
#查询人员和部门所有信息 select * from person inner join dept on person.did =dept.did; |
效果: 大家可能会发现, 内连接查询与多表联合查询的效果是一样的.
select * from person inner join dept on person.did =dept.did;
2 左外连接查询 (左边表中的数据优先全部显示)
1
2
|
#查询人员和部门所有信息 select * from person left join dept on person.did =dept.did; |
效果:人员表中的数据全部都显示,而 部门表中的数据符合条件的才会显示,不符合条件的会以 null 进行填充.
select * from person left join dept on person.did =dept.did;
3 右外连接查询 (右边表中的数据优先全部显示)
1
2
|
#查询人员和部门所有信息 select * from person right join dept on person.did =dept.did; |
效果:正好与[左外连接相反]
select * from person right join dept on person.did =dept.did;
4 全连接查询(显示左右表中全部数据)
全连接查询:是在内连接的基础上增加 左右两边没有显示的数据
注意: mysql并不支持全连接 full JOIN 关键字
注意: 但是mysql 提供了 UNION 关键字.使用 UNION 可以间接实现 full JOIN 功能
1
2
3
4
5
|
#查询人员和部门的所有数据 SELECT * FROM person LEFT JOIN dept ON person.did = dept.did UNION SELECT * FROM person RIGHT JOIN dept ON person.did = dept.did; |
SELECT * FROM person LEFT JOIN dept ON person.did = dept.did
UNION
SELECT * FROM person RIGHT JOIN dept ON person.did = dept.did;
注意: UNION 和 UNION ALL 的区别:UNION 会去掉重复的数据,而 UNION ALL 则直接显示结果
三 复杂条件多表查询
1. 查询出 教学部 年龄大于20岁,并且工资小于40000的员工,按工资倒序排列.(要求:分别使用多表联合查询和内连接查询)
#1.多表联合查询方式:
select * from person where did =(select did from dept where dname ='教学部')
and age>20
and salary <40000
ORDER BY salary DESC; #2.内连接查询方式:
SELECT * FROM person p1 INNER JOIN dept d2 ON p1.did= d2.did
and d2.dname='教学部'
and age>20
and salary <40000
ORDER BY salary DESC;
2.查询每个部门中最高工资和最低工资是多少,显示部门名称
select MAX(salary),MIN(salary),dept.dname from
person LEFT JOIN dept
ON person.did = dept.did
GROUP BY person.did;
四 子语句查询
子查询(嵌套查询): 查多次, 多个select
注意: 第一次的查询结果可以作为第二次的查询的 条件 或者 表名 使用.
子查询中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等关键字. 还可以包含比较运算符:= 、 !=、> 、<等.
1.作为表名使用
1
2
3
|
select * from ( select * from person) as 表名(起别名,不能带引号); ps:大家需要注意的是: 一条语句中可以有多个这样的子查询,在执行时,最里层括号(sql语句) 具有优先执行权.<br>注意: as 后面的表名称不能加引号( '' ) |
2.求最大工资那个人的姓名和薪水
1.求最大工资
select max(salary) from person;
2.求最大工资那个人叫什么
select name,salary from person where salary=53000; 合并
select name,salary from person where salary=(select max(salary) from person);
3. 求工资高于所有人员平均工资的人员
1.求平均工资
select avg(salary) from person; 2.工资大于平均工资的 人的姓名、工资
select name,salary from person where salary > 21298.625; 合并
select name,salary from person where salary >(select avg(salary) from person);
4.练习
1.查询平均年龄在20岁以上的部门名
2.查询教学部 下的员工信息
3.查询大于所有人平均工资的人员的姓名与年龄
#1.查询平均年龄在20岁以上的部门名
SELECT * from dept where dept.did in (
select dept_id from person GROUP BY dept_id HAVING avg(person.age) > 20
); #2.查询教学部 下的员工信息
select * from person where dept_id = (select did from dept where dname ='教学部'); #3.查询大于所有人平均工资的人员的姓名与年龄
select * from person where salary > (select avg(salary) from person);
5.关键字
假设any内部的查询语句返回的结果个数是三个,如:result1,result2,result3,那么, select ...from ... where a > any(...);
->
select ...from ... where a > result1 or a > result2 or a > result3;
ANY关键字
ALL关键字与any关键字类似,只不过上面的or改成and。即: select ...from ... where a > all(...);
->
select ...from ... where a > result1 and a > result2 and a > result3;
ALL关键字
some关键字和any关键字是一样的功能。所以: select ...from ... where a > some(...);
->
select ...from ... where a > result1 or a > result2 or a > result3;
SOME关键字
EXISTS 和 NOT EXISTS 子查询语法如下: SELECT ... FROM table WHERE EXISTS (subquery)
该语法可以理解为:主查询(外部查询)会根据子查询验证结果(TRUE 或 FALSE)来决定主查询是否得以执行。 mysql> SELECT * FROM person
-> WHERE EXISTS
-> (SELECT * FROM dept WHERE did=5);
Empty set (0.00 sec)
此处内层循环并没有查询到满足条件的结果,因此返回false,外层查询不执行。 NOT EXISTS刚好与之相反 mysql> SELECT * FROM person
-> WHERE NOT EXISTS
-> (SELECT * FROM dept WHERE did=5);
+----+----------+-----+-----+--------+------+
| id | name | age | sex | salary | did |
+----+----------+-----+-----+--------+------+
| 1 | alex | 28 | 女 | 53000 | 1 |
| 2 | wupeiqi | 23 | 女 | 29000 | 1 |
| 3 | egon | 30 | 男 | 27000 | 1 |
| 4 | oldboy | 22 | 男 | 1 | 2 |
| 5 | jinxin | 33 | 女 | 28888 | 1 |
| 6 | 张无忌 | 20 | 男 | 8000 | 3 |
| 7 | 令狐冲 | 22 | 男 | 6500 | 2 |
| 8 | 东方不败 | 23 | 女 | 18000 | NULL |
+----+----------+-----+-----+--------+------+
8 rows in set 当然,EXISTS关键字可以与其他的查询条件一起使用,条件表达式与EXISTS关键字之间用AND或者OR来连接,如下: mysql> SELECT * FROM person
-> WHERE AGE >23 AND NOT EXISTS
-> (SELECT * FROM dept WHERE did=5);
提示:
•EXISTS (subquery) 只返回 TRUE 或 FALSE,因此子查询中的 SELECT * 也可以是 SELECT 1 或其他,官方说法是实际执行时会忽略 SELECT 清单,因此没有区别。
EXISTS 关键字
五 其他查询
1.临时表查询
需求: 查询高于本部门平均工资的人员
解析思路: 1.先查询本部门人员平均工资是多少.
2.再使用人员的工资与部门的平均工资进行比较
#1.先查询部门人员的平均工资
SELECT did,AVG(salary)as sal from person GROUP BY did; #2.再用人员的工资与部门的平均工资进行比较
SELECT * FROM person as p1,
(SELECT did,AVG(salary)as '平均工资' from person GROUP BY did) as p2
where p1.did = p2.did AND p1.salary >p2.`平均工资`;#注意引号不一样 ps:在当前语句中,我们可以把上一次的查询结果当前做一张表来使用.因为p2表不是真是存在的,所以:我们称之为 临时表
临时表:不局限于自身表,任何的查询结果集都可以认为是一个临时表.
代码示例
2. 判断查询 IF关键字
需求1 :根据工资高低,将人员划分为两个级别,分别为 高端人群和低端人群。显示效果:姓名,年龄,性别,工资,级别
select *,if(p.salary > 10000,'高端人群','低端人群') as '级别' from person p;
#ps: 语法: IF(条件表达式,"结果为true",'结果为false');
代码示例
需求2: 根据工资高低,统计每个部门人员收入情况,划分为 富人,小资,平民,吊丝 四个级别, 要求统计四个级别分别有多少人
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#语法一: SELECT CASE WHEN STATE = '1' THEN '成功' WHEN STATE = '2' THEN '失败' ELSE '其他' END FROM 表; #语法二: SELECT CASE age WHEN 23 THEN '23岁' WHEN 27 THEN '27岁' WHEN 30 THEN '30岁' ELSE '其他岁' END FROM person; |
select dname '部门',
sum(case when salary >50000 then 1 else 0 END) as '富人',
sum(case when salary between 29000 and 50000 then 1 else 0 end) as '小资',
sum(case when salary between 10000 and 29000 then 1 else 0 end) as '平民',
sum(case when salary < 10000 then 1 else 0 end) as '屌丝'
from person,dept where person.did = dept.did group by person.did;
代码示例
六 SQL逻辑查询语句执行顺序(重点***)
先来一段伪代码,首先你能看懂么?
1
2
3
4
5
6
7
8
9
|
SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOIN <right_table> ON <join_condition> WHERE <where_condition> GROUP BY <group_by_list> HAVING <having_condition> ORDER BY <order_by_condition> LIMIT <limit_number> |
如果你知道每个关键字的意思和作用,并且你还用过的话,那再好不过了。但是,你知道这些语句,它们的执行顺序你清楚么?如果你非常清楚,你就没有必要再浪费时间继续了;如果你不清楚,非常好!!! 请点击我...
七 外键约束
1.问题?
什么是约束:约束是一种限制,它通过对表的行或列的数据做出限制,来确保表的数据的完整性、唯一性
2.问题?
以上两个表 person和dept中, 新人员可以没有部门吗?
3.问题?
新人员可以添加一个不存在的部门吗?
4.如何解决以上问题呢?
简单的说,就是对两个表的关系进行一些约束 (即: froeign key).
foreign key 定义:就是表与表之间的某种约定的关系,由于这种关系的存在,能够让表与表之间的数据,更加的完整,关连性更强。
5.具体操作
5.1创建表时,同时创建外键约束
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
CREATE TABLE IF NOT EXISTS dept ( did int not null auto_increment PRIMARY KEY , dname VARCHAR (50) not null COMMENT '部门名称' )ENGINE=INNODB DEFAULT charset utf8; CREATE TABLE IF NOT EXISTS person( id int not null auto_increment PRIMARY KEY , name VARCHAR (50) not null , age TINYINT(4) null DEFAULT 0, sex enum( '男' , '女' , '人妖' ) NOT NULL DEFAULT '人妖' , salary decimal (10,2) NULL DEFAULT '250.00' , hire_date date NOT NULL , dept_id int (11) DEFAULT NULL , CONSTRAINT fk_did FOREIGN KEY (dept_id) REFERENCES dept(did) -- 添加外键约束 )ENGINE = INNODB DEFAULT charset utf8; |
5.2 已经创建表后,追加外键约束
1
2
3
4
5
|
#添加外键约束 ALTER table person add constraint fk_did FOREIGN key (dept_id) REFERENCES dept(did); #删除外键约束 ALTER TABLE person drop FOREIGN key fk_did; |
定义外键的条件:
(1)外键对应的字段数据类型保持一致,且被关联的字段(即references指定的另外一个表的字段),必须保证唯一
(2)所有tables的存储引擎必须是InnoDB类型.
(3)外键的约束4种类型: 1.RESTRICT 2. NO ACTION 3.CASCADE 4.SET NULL
数据库设计三范式: http://www.cnblogs.com/aaronthon/p/8480011.html
FOREIGN MySQL 之 多表查询的更多相关文章
- MySQL之多表查询一 介绍 二 多表连接查询 三 符合条件连接查询 四 子查询 五 综合练习
MySQL之多表查询 阅读目录 一 介绍 二 多表连接查询 三 符合条件连接查询 四 子查询 五 综合练习 一 介绍 本节主题 多表连接查询 复合条件连接查询 子查询 首先说一下,我们写项目一般都会建 ...
- day15(mysql 的多表查询,事务)
mysql之多表查询 1.合并结果集 作用:合并结果集就是把两个select语句查询的结果连接到一起! /*创建表t1*/ CREATE TABLE t1( a INT PRIMARY KEY , b ...
- Mariadb/MySQL数据库单表查询基本操作及DML语句
Mariadb/MySQL数据库单表查询基本操作及DML语句 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一数据库及表相关概述 1>.数据库操作 创建数据库: CREATE ...
- day 39 MySQL之多表查询
MySQL之多表查询 阅读目录 一 介绍 二 多表连接查询 三 符合条件连接查询 四 子查询 五 综合练习 一 介绍 本节主题 多表连接查询 复合条件连接查询 子查询 首先说一下,我们写项目一般都 ...
- Vc数据库编程基础MySql数据库的表查询功能
Vc数据库编程基础MySql数据库的表查询功能 一丶简介 不管是任何数据库.都会有查询功能.而且是很重要的功能.上一讲知识简单的讲解了表的查询所有. 那么这次我们需要掌握的则是. 1.使用select ...
- MySQL之单表查询 一 单表查询的语法 二 关键字的执行优先级(重点) 三 简单查询 四 WHERE约束 五 分组查询:GROUP BY 六 HAVING过滤 七 查询排序:ORDER BY 八 限制查询的记录数:LIMIT 九 使用正则表达式查询
MySQL之单表查询 阅读目录 一 单表查询的语法 二 关键字的执行优先级(重点) 三 简单查询 四 WHERE约束 五 分组查询:GROUP BY 六 HAVING过滤 七 查询排序:ORDER B ...
- mysql数据库优化课程---11、mysql普通多表查询
mysql数据库优化课程---11.mysql普通多表查询 一.总结 一句话总结:select user.username,user.age,class.name,class.ctime from u ...
- day 38 MySQL之单表查询
MySQL之单表查询 阅读目录 一 单表查询的语法 二 关键字的执行优先级(重点) 三 简单查询 四 WHERE约束 五 分组查询:GROUP BY 六 HAVING过滤 七 查询排序:ORDER ...
- MySQL的联表查询
MySQL的联表查询 首选:分析查询的字段来自哪些表 进而:确定交集 然后:确定判断的条件 比如:从student表 和 result表 查学号.考试名称.学时.考试日期.考试成绩 表1: 学号 考试 ...
随机推荐
- [数据结构与算法分析(Mark Allen Weiss)]二叉树的插入与删除 @ Python
二叉树的插入与删除,来自Mark Allen Weiss的<数据结构与算法分析>. # Definition for a binary tree node class TreeNode: ...
- Android批量图片加载经典系列——使用LruCache、AsyncTask缓存并异步加载图片
一.问题描述 使用LruCache.AsyncTask实现批量图片的加载并达到下列技术要求 1.从缓存中读取图片,若不在缓存中,则开启异步线程(AsyncTask)加载图片,并放入缓存中 2.及时移除 ...
- Java access to the Domino Objects, Part 1
From: https://www.ibm.com/developerworks/lotus/library/ls-Java_access_pt1/index.html Overview Java a ...
- python 网络工具 scapy 介绍
作者介绍,这是个万能的网络工具,除了可以查看 TCP/IP 各层的报文,还可以发送报文.可以说是一个万能工具,作者嚣张的说, “it can replace hping, 85% of nmap, a ...
- SoapUI Pro Project Solution Collection-Test Step Object
Package com.eviware.soapui.model.testsuite used for access the current testsuite object, like test c ...
- fiddler展示serverIP方法
转载自:http://www.xuanfengge.com/fiddler-displays-the-set-ip-method.html 前言 由于web前端在多个环境中开发,需要经常更换host, ...
- Failed to execute goal org.mybatis.generator:mybatis-generator-maven-plugin:1.3.2:generate
(1)将Maven项目先clean,接着install下 (2)运行mvn mybatis-generator:generate命令 注意修改generatorConfig.xml的location: ...
- OpenLayers 官网例子的中文详解
https://segmentfault.com/a/1190000009679800?utm_source=tag-newest 当你希望实现某种功能的时候,即使你对 openlayers 几乎一窍 ...
- 5.翻译系列:EF 6中数据库的初始化(EF 6 Code-First 系列)
原文地址:http://www.entityframeworktutorial.net/code-first/database-initialization-in-code-first.aspx EF ...
- Atitit 医学之道 attilax总结
Atitit 医学之道 attilax总结 1. 相关的学科3 1.1. 口腔医学 ok3 1.2. 人体解剖学 ok3 1.3. 生理学 ok3 1.4. 病理学 ok3 1.5. 骨伤科学 ...