多表查询
1、分类
-| 合并结果集(了解)
-| 连接查询
-| 子查询
合并结果集
-| 要求被合并的表中,列的类型和列数相同
-| union 去除重复行
-| UNION ALL, 不去除重复行
select * from cd
union ALL
SELECT * FROM ab;
连接查询
1.分类
-| 内连接
-| 外连接
-| 左外连接
-| 右外连接
-| 全外连接(MySQL不支持)
自然连接(属于一种简化)
2.内连接
-| 方言:select * from 表1 别名1, 表2, 别名2 where 别名1.xx = 别名2.xx
-| 标准:select * from 表1 别名1 inner join 表2 别名2 on 别名1.xx = 别名2.xx
-| 自然: select * from 表1 别名1 natural join 表2 别名2
内连接查询出的所有记录都满足条件。
3. 外连接
左外:select * from 表1 别名1 left outer join 表2 别名2 on 别名1.xx = 别名2.xx
>左表记录无论是否满足条件都会查询出来,而右表只有满足条件才能出来。左表中不满足条件的记录,其右表部分为NULL
左外自然:select * from 表1 别名1 NATURAL LEET OUTER JOIN 表2 别名2 ON 别名1.xx == 别名2.xx
右外:select * from 表1 别名1 NATURAL RIGHT OUTER JOIN 表2 别名2 ON 别名1.xx = 别名2.xx
>右表记录无论是否满足条件都会查询出来,而左表只有满足条件才能出来。右表中不满足条件的记录,其左表部分为NULL
左外自然:select * from 表1 别名1 NATURAL RIGHT OUTER JOIN 表2 别名2 ON 别名1.xx == 别名2.xx
全链接:可以使用UNION来完成全链接
子查询:
查询中有查询(查看select关键字的个数!)
1.出现的位置
where后作为条件存在
from后作为表存在(多行多列)
2.条件
单行单列:SELECT * FROM 表1 别名1 WHERE 列1 [=、 >、 <、 >=、 <=、 != ](SELECT 列 FROM 表2 别名2 WHERE 条件)
多行单列:SELECT * FROM 表1 别名1 WHERE 列1 [IN、 ALL、 ANY ](SELECT 列 FROM 表2 别名2 WHERE 条件)
单行多列:SELECT * FROM 表1 别名1 WHERE 列1 (列1, 列2)IN(SELECT 列 FROM 表2 别名2 WHERE 条件)
多行多列:SELECT * FROM 表1 别名1 (SELECT ......)别名2 WHERE 条件
-- ---------------------mysql内连接查询(方言)----------------------
-- 查询的笛卡尔积
-- {a, b, c} {1, 2}
-- {a1, a2, b1, b2, c1, c2}
-- 在查询中会产生大量的垃圾数据
SELECT *
FROM emp, dept; -- 会产生笛卡尔积
-- ----------加入查询条件-----------
SELECT *
FROM emp, dept
WHERE emp.deptno = dept.deptno;
/*
打印:所有员工的姓名、工资、以及部门名称(去笛卡尔积)
*/
SELECT e.ename as '姓名', e.sal as '工资', d.dname as '部门名称'
FROM emp e, dept d -- 为表加入别名
WHERE e.deptno = d.deptno;
-- ---------------------mysql内连接查询(标准)----------------------
-- 标准内连接查询(在开发中建议使用标准查询语句,保证兼容性,防止数据库变更时重写SQL语句)
SELECT e.ename as '姓名', e.sal as '工资', d.dname as '部门名称'
FROM emp e INNER JOIN dept d -- 查询的内连接
ON e.deptno = d.deptno; -- 此处可以使用where关键字 但是作为标准使用方式要使用on
-- ---------------------mysql内连接查询(自然)----------------------
-- 自然查询 NATURAL(此方法可读性较低,不建议使用)
SELECT e.ename as '姓名', e.sal as '工资', d.dname as '部门名称'
FROM emp e NATURAL JOIN dept d; -- 使用natural关键字 在查询中系统会自动都去关联表中查找相同的列进行匹配
-- ---------------SQL查询外连接-------------------
/* 外连接有一住一次,左外(左表)为主
即:emp e为主,主表中所有的记录无论是否满足,都打印出来
当不满足条件时,右表部分使用null补位
*/
SELECT e.ename, e.sal, d.dname -- 可以使用ifnull函数,将null变为给定信息
-- SELECT e.ename, e.sal, IFNULL(d.dname,'无部门')
FROM emp e LEFT OUTER JOIN dept d -- 左外连接
ON e.deptno = d.deptno;
-- 右链接
SELECT e.ename, e.sal, d.dname -- 查询效果与左连接相反(表中财务部没有员工,只显示部门名称,其他列用null补位,张三没有与主表相连,所以无法查询到)
FROM emp e RIGHT OUTER JOIN dept d
ON e.deptno = d.deptno;
-- 全外链接(左表和右表没有出现的信息都要进行补位)
SELECT e.ename, e.sal, d.dname
FROM emp e FULL OUTER JOIN dept d
ON e.deptno = d.deptno;
-- 注意:mysql中不支持全外链接查询,可以使用结果合并集模拟次操作
SELECT e.ename, e.sal, d.dname
FROM emp e LEFT OUTER JOIN dept d
ON e.deptno = d.deptno -- 注意此处不能出现分号(分号表示一条查询语句的结束)
UNION -- 用结果集弥补全外查询
SELECT e.ename, e.sal, d.dname
FROM emp e RIGHT OUTER JOIN dept d
ON e.deptno = d.deptno;
-- ----------------------子查询------------------------------
/*
查询本公司工资最高的员工的详细信息
子查询可以出现的位置:
FROM
WHERE
*/
SELECT MAX(sal) FROM emp; -- 查询最高工资
SELECT * -- 查询指定工资(最高工资)的员工的所有信息
FROM emp e
WHERE sal=(SELECT MAX(sal) FROM emp); -- 在查询条件中加入查询条件(子查询)
-- 出现位置在from中
SELECT e.empno, e.ename
FROM(SELECT * FROM emp WHERE deptno=30) e -- 以部门为30的员工为基础进行二次查询,注意要取一个别名
WHERE e.empno = 1002;
-- 子查询的结果集分为:
-- 单行单列, 多行单列、单行单列、 多行多列
/*单行单列:打印高于平均工资的所有员工*/
SELECT *
FROM emp
WHERE sal > (SELECT AVG(sal) FROM emp);
/*多行单列:打印高于30部门所有员工工资的员工*/
SELECT *
FROM emp
WHERE sal > ANY (SELECT sal FROM emp WHERE deptno=20);
/*多行单列:打印高于任意经理工资的员工*/
SELECT *
FROM emp
WHERE sal > ANY (SELECT sal FROM emp WHERE job='经理');
/*单行多列:打印工作、部门和工资都与殷天正相同的员工 */
SELECT *
FROM emp
WHERE(job, deptno, sal) IN (SELECT job, deptno, sal FROM emp WHERE ename='殷天正'); -- 可以理解为比较两个对象是否相等
/*多行多列:查询30部门中所以员工的编号和姓名*/
SELECT e.empno, e.ename
FROM(SELECT * FROM emp WHERE deptno=30) e
mysql数据源:
/*
Navicat MySQL Data Transfer
Source Server : erp
Source Server Version : 50022
Source Host : localhost:3306
Source Database : exam
Target Server Type : MYSQL
Target Server Version : 50022
File Encoding : 65001
Date: 2019-09-12 16:43:52
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for dept
-- ----------------------------
DROP TABLE IF EXISTS `dept`;
CREATE TABLE `dept` (
`deptno` int(11) NOT NULL,
`dname` varchar(50) default NULL,
`loc` varchar(50) default NULL,
PRIMARY KEY (`deptno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of dept
-- ----------------------------
INSERT INTO `dept` VALUES ('10', '教研部', '北京');
INSERT INTO `dept` VALUES ('20', '学工部', '上海');
INSERT INTO `dept` VALUES ('30', '销售部', '广州');
INSERT INTO `dept` VALUES ('40', '财务部', '武汉');
-- ----------------------------
-- Table structure for emp
-- ----------------------------
DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (
`empno` int(11) NOT NULL,
`ename` varchar(50) default NULL,
`job` varchar(50) default NULL,
`mgr` int(11) default NULL,
`hiredate` date default NULL,
`sal` decimal(7,2) default NULL,
`COMM` decimal(7,2) default NULL,
`deptno` int(11) default NULL,
PRIMARY KEY (`empno`),
KEY `fk_emp` (`mgr`),
CONSTRAINT `fk_emp` FOREIGN KEY (`mgr`) REFERENCES `emp` (`empno`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of emp
-- ----------------------------
INSERT INTO `emp` VALUES ('1001', '甘宁', '文员', '1013', '2000-12-17', '8000.00', null, '20');
INSERT INTO `emp` VALUES ('1002', '黛绮丝', '销售员', '1006', '2001-02-20', '16000.00', '3000.00', '30');
INSERT INTO `emp` VALUES ('1003', '殷天正', '销售员', '1006', '2001-02-22', '12500.00', '5000.00', '30');
INSERT INTO `emp` VALUES ('1004', '刘备', '经理', '1009', '2001-04-02', '29750.00', null, '20');
INSERT INTO `emp` VALUES ('1005', '谢逊', '销售员', '1006', '2001-09-28', '12500.00', '14000.00', '30');
INSERT INTO `emp` VALUES ('1006', '关羽', '经理', '1009', '2001-05-01', '28500.00', null, '30');
INSERT INTO `emp` VALUES ('1007', '张飞', '经理', '1009', '2001-09-01', '24500.00', null, '10');
INSERT INTO `emp` VALUES ('1008', '诸葛亮', '分析师', '1004', '2007-09-01', '30000.00', null, '20');
INSERT INTO `emp` VALUES ('1009', '曾阿牛', '董事长', null, '2001-11-17', '50000.00', null, '10');
INSERT INTO `emp` VALUES ('1010', '韦一笑', '销售员', '1006', '2001-09-08', '15000.00', '0.00', '30');
INSERT INTO `emp` VALUES ('1011', '周泰', '文员', '1008', '2007-05-28', '11000.00', null, '20');
INSERT INTO `emp` VALUES ('1012', '程普', '文员', '1006', '2001-12-03', '9500.00', null, '30');
INSERT INTO `emp` VALUES ('1013', '庞统', '分析师', '1004', '2001-12-09', '30000.00', null, '20');
INSERT INTO `emp` VALUES ('1014', '黄盖', '文员', '1007', '2002-01-23', '13000.00', null, '10');
INSERT INTO `emp` VALUES ('1015', '张三', '保洁员', '1009', '1999-09-09', '80000.00', '90000.00', '50');
-- ----------------------------
-- Table structure for salgrade
-- ----------------------------
DROP TABLE IF EXISTS `salgrade`;
CREATE TABLE `salgrade` (
`grade` int(11) NOT NULL,
`losal` int(11) default NULL,
`hisal` int(11) default NULL,
PRIMARY KEY (`grade`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of salgrade
-- ----------------------------
INSERT INTO `salgrade` VALUES ('1', '7000', '12000');
INSERT INTO `salgrade` VALUES ('2', '12010', '14000');
INSERT INTO `salgrade` VALUES ('3', '14010', '20000');
INSERT INTO `salgrade` VALUES ('4', '20010', '30000');
INSERT INTO `salgrade` VALUES ('5', '30010', '99990');
-- ----------------------------
-- Table structure for stu
-- ----------------------------
DROP TABLE IF EXISTS `stu`;
CREATE TABLE `stu` (
`sid` int(11) NOT NULL,
`sname` varchar(50) default NULL,
`age` int(11) default NULL,
`gender` varchar(10) default NULL,
`province` varchar(50) default NULL,
`tuition` int(11) default NULL,
PRIMARY KEY (`sid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of stu
-- ----------------------------
INSERT INTO `stu` VALUES ('1', '王永', '23', '男', '北京', '1500');
INSERT INTO `stu` VALUES ('2', '张雷', '25', '男', '辽宁', '2500');
INSERT INTO `stu` VALUES ('3', '李强', '22', '男', '山东', '3500');
INSERT INTO `stu` VALUES ('4', '宋永合', '18', '男', '成都', '4500');
INSERT INTO `stu` VALUES ('5', '宋永合', '20', '女', '湖北', '1000');