准备工作:
注意:首先导入数据库,执行该语句前,必须先在Mysql服务器中创建company数据库,必须为空数据库。
#环境变量的设置
C:\Users\px>set path=C:\Program Files\MySQL\MySQL Server 5.7\bin
C:\Users\adm>mysql -u root -p company < C:/backup/company.sql
一、内连接查询:
在MySQL中实现连接查询有两种语法:
1. 在from子句中利用逗号区分多个表,在where子句中通过逻辑表达式来实现匹配条件,从而实现表的连接。
2. ANSI连接语法形式,在from子句中使用“join on”关键字,而连接条件写在关键字on子句中。推荐使用第二种方式。
按照匹配条件,内连接查询可以分为两类:等值连接;不等连接。
内连接查询语法为:
1 2 3 |
|
//参数filedn 表示所要查询的字段名称,来源于所连接的表join_tablename1 和 join_tablename2,关键字inner join表进行内连接,join_condition表示进行匹配的条件。
2.1 自连接:
自连接就是指表与其自身进行连接。
#查询每一位雇员的姓名和职位
> select e.ename, e.job from t_employee e;
#查询每个雇员的姓名、职位、领导姓名(关键是确定匹配条件)
> select e.ename, e.job, l.ename
> from t_employee e inner join t_employee l
> on e.mgr=l.empno; (注意:如果省略掉on之后的语句则为笛卡尔积)
2.2等值连接:
内连接查询中的等值连接,就是在关键字on后的匹配条件中通过等于关系运算符“=”来实现等值条件。
#查询每个雇员的编号、姓名、职位、部门名称和位置
> select e.empno, e.ename, e.job, d.dname, d.loc
> from t_employee e inner join t_dept d
> on e.deptno=d.deptno;
2.3不等连接:
内连接查询中的不等连接,就是在关键字on后的匹配条件中通过除了等于关系运算符来实现不等条件外,可以使用的关系运算符包含> >= < <= !=
#查询雇员编号大于其领导的每个雇员的姓名、职位、领导姓名
> select e.ename, e.job, l.ename
> from t_employee e inner join t_employee l
> on e.mgr=l.empno and e.empno>l.empno
二、外连接查询:
外连接查询会返回所操作表中至少一个表的所有数据。外连接分为三类:左外连接、右外连接、全外连接
语法为:
1 2 3 |
|
3.1左外连接:
外连接查询中的左外连接,就是指新关系中执行匹配条件时,以关键字left join 左边的表为参考。
#查询每个雇员的姓名、职位、领导姓名
> select e.ename, e.job, l.ename
> from t_employee e left join t_employee l
> on e.mgr=l.empno; (注:除了选择相匹配的数据记录,还包含关联左边表中不匹配的数据记录。 注意结果中的KING记录)
3.2右外连接:
外连接查询中的右外连接,就是指新关系中执行匹配条件时,以关键字right join 右边的表为参考。
三、合并查询数据记录:
在MySQL中通过关键字UNION来实现并操作,即可以通过其将多个select语句的查询结果合并在一起组成新的关系。
#构建一个新的表t_dept2
> create table t_dept2 select * from t_dept;
> update t_dept2 set loc='London'where deptno!=10;
1. 关键字union的合并操作
关键字union会把查询结果集直接合并在一起,同时将会去掉重复数据记录。
> select * from t_dept union select * from t_dept2;
2. 关键字union all的合并操作
关键字union all会把查询结果集直接合并在一起。
> select * from t_dept union all select * from t_dept2;
四、子查询:
5.1 为什么使用子查询:
在MySQL中虽然可以通过连接查询实现多表查询数据记录,但却不建议使用。这是因为连接查询的性能很差。因此出现了连接查询的替代者子查询。推荐使用子查询来实现多表查询数据记录。
5.2 返回结果为单行单列和单行多列子查询:
当子查询的返回结果为单行蛋类数据记录时,该子查询语句一般在主查询语句的where子句中,通常会包含比较运算符(> < = != 等)
5.2.1 单行单列子查询:
#查询工资比Smith高的全部雇员信息:
> select sal from t_employee where ename='smith';
> select * from t_employee where sal>(select sal from t_employee where ename='smith');
5.2.2 单行多列子查询:
where子句中的子查询除了是返回单行单列的数据记录外,还可以是返回多行多列的数据记录,不过这种子查询很少出现。
# 查询名为SMITH雇员的工资和职位:
> select sal,job from t_employee where ename='smith';
> select ename,sal,job from t_employee where(sal,job)=(select sal,job from t_employee where ename='smith');
5.3 返回结果为多行单列子查询:
当子查询的返回结果为多行单列数据记录时,该子查询语句一般会在主查询语句的where子句中出现,通常会包含IN ANY ALL EXISTS等关键字。
5.3.1 带有关键字in的子查询:
当主查询的条件在子查询的查询结果中时,可以通过关键字in来进行判断。相反,如果想实现主查询的条件不在子查询的查询结果中时,可以通过关键字not in来进行判断。
# 在数据库company中,查询雇员表中的数据记录,这些数据记录的部门编号必须在部门表中出现
> update t_employee set deptno=50 where ename='miller'; (准备工作)
> select deptno from t_dept;
> select * from t_employee where deptno in(select deptno from t_dept);
> select * from t_employee where deptno not in(select deptno from t_dept);
5.3.2 带有关键字any的子查询:
关键字any:主查询的条件为满足子查询的查询结果中任意一条数据记录,该关键字有三种匹配方式;
1. =any:其功能与关键字in一样
2. > any(>=any):只要大于(大于等于)子查询中最小的一个即可。
3. < any(<=any):只要小于(小于等于)子查询中最大的一个即可。
#(查询雇员工资不低于职位为manager的工资)
> select sal from t_employee where job='manager';
> select ename, sal from t_employee where sal>any(select sal from t_employee where job='manager');
5.3.3 带有关键字all的子查询:
关键字all用来表示主查询的条件为满足子查询返回查询结果中所有数据记录,有两种匹配方式:
1. > all(>=all):比子查询结果中最大的还要大(大于等于)的数据记录;
2. < all(<= all):比子查询结果中最小的还要小(小于等于)的数据记录。
示例:
> select ename, sal from t_employee where sal>all(select sal from t_employee where job='manager');
5.3.4 带有关键字exists的子查询:
关键字exists是一个boolean类型,当能返回结果集时为true,不能返回结果集时为false。查询时exists对外表采用遍历方式逐条查询,每次查询都会比较exists的条件语句,当exists里的条件语句返回记录行时则条件为真,此时返回当前遍历到的记录;反之,如果exists里条件语句不能返回记录行,则丢弃当前遍历到的记录。
#查询部门表中的的deptno和depname,如果该部门没有员工,则显示该部门
> select * from t_employee a, t_dept c where a.deptno=c.deptno;
> select * from t_dept c where not exists(select * from t_employee where deptno=c.deptno);
> select * from t_dept c where exists(select * from t_employee where deptno=c.deptno);
5.4 返回结果为多行多列子查询:
当子查询的返回结果为多行多列数据记录时,该子查询语句一般会在主查询语句的from子句里,被当作一张临时表的方式来处理。
# 查询雇员表中各部门的部门号、部门名称、部门地址、雇员人数、和平均工资:
通过内连接来实现:
> select d.deptno,d.dname, d.loc, count(e.empno) number, avg(e.sal) average
> from t_employee e inner join t_dept d
> on e.deptno=d.deptno
> group by d.deptno desc, d.dname, d.loc;
#计算笛卡尔积的数据记录数
> select count(*) number from t_employee, t_dept;
Comments