MySQL多表查询详解

Wesley13
• 阅读 399

多表查询

1. 表与表之间的关系

<1> 一对一

  • 用户表和身份信息表,用户表是主表

  • 男人表、女人表

      create table man(
          mid int primary key auto_increment,
          mname varchar(32),
          wid int unique        
      );
    
      create table woman(
          wid int primary key auto_increment,
          wname varchar(32)
      );
    

<2> 一对多

  • 最常见得表关系,用户表和订单表

  • 员工表、部门表 create table emp( empno int primary key auto_increment, ename varchar(32) deptno int );

      create teble dept(
          deptno int primary key auto_increment,
          dname varchar(32)
      );
    

<3> 多对多

  • 学生表和课程表,通常情况都是将多对多的关系拆分为一对多或者多对一的关系

  • 至少需要三张表

      create table student(
          cid int primary key auto_increment,
          sname varchar(32)
      );
    
      insert into student (sname) values('小张');
      insert into student (sname) values('小李');
      insert into student (sname) values('小王');
    
      create table course(
          sid int primary key auto_increment,
          cname varchar(32)
      );
    
      insert into course (cname) values('语文');
      insert into student (sname) values('数学');
      insert into student (sname) values('英语');
      insert into student (sname) values('化学');
    
      create table s_c(
          cid int,
          sid int
      );
    
      insert into s_c(sid, cid) values (1, 1);
      insert into s_c(sid, cid) values (1, 2);
      insert into s_c(sid, cid) values (1, 3);
      insert into s_c(sid, cid) values (1, 4);
      insert into s_c(sid, cid) values (2, 2);
      insert into s_c(sid, cid) values (2, 4);
      insert into s_c(sid, cid) values (3, 1);
      insert into s_c(sid, cid) values (3, 3);
    

2. 为什么要使用多张表

  • 避免出现大量的数据的冗余
  • 并不是表拆的越多越好,需要根据实际情况进行拆分

3. 概念

  • 同时查询多张表

4. 多表查询的分类

<1> 合并查询

  • union, union all

  • 合并结果集,就是把两个select语句的查询结果合并到一起。(相当于并集)

  • 合并的两个结果,列数和列的顺序,类型需要一致

      create table emp(
          empno int primary key auto_increment,
          ename varchar(32)
      );
    
      create table dept(
          depeno int primary key auto_increment,
          dname varchar(32)
      );
    
      select * from emp union select * from dept;
      select * from emp union all select * from dept;
    

<2> 连接查询

-- 员工表
create table emp(
    empno int primary key auto_increment,  # 员工编号
    ename varchar(32),  # 员工姓名
    job varchar(32),      # 员工职位
    mgr int,                          # 上级编号
    hiredate date,          # 入职时间
    sal double,                  # 薪资
    comm double,              # 奖金
    deptno int                  # 员工所属部门
);

-- 部门表
create table dept(
    deptno int primary key auto_increment,  # 部门编号
    dname varchar(32),  # 部门名称
    loc varchar(32)          # 部门地址
);
  • 内连接

    • inner join .... on 、 join , ,
    • inner join 是一个比较运算符,只返回符合条件的行
    • 例如:
      • select * from emp inner join dept on emp.deptno=dept.deptno;
      • select * from emp e, dept d where e.deptno = d.deptno;
      • select * from emp e join dept d where e.deptno = d.deptno;
  • 外连接

    • 左外连接 LEFT OUTER JOIN | left join .... on
      • 代表查询,左边行的全部,右边没有则null
      • select * from emp e LEFT OUTER JOIN dept d on e.deptno = d.deptno;
    • 右外连接 right join | right outer join .... on
      • 有连接包含right join 右表所有的行,如果左表中某行在右表没有匹配,则结果中对应的左表的部分全部为空(null)
      • select * from emp e RIGHT OUTER JOIN dept d on e.deptno = d.deptno;
  • 自连接

    • 自连接就是说,在同一个数据表中,看作是两个表,表示查找每个人的领导,如果没有领导,则显示无领导
    • 把一张表看作成两张表,一张员工表,一张领导表,都是emp表
    • select e.ename, el.ename from emp e left join emp el on e.mgr = el.empno;
  • 自然连接: natural join (join) | natural left join (同 left join) | natural right join (同 right join)

    • 自然连接会自动判断,以两个表中相同的字段为连接条件,返回查询结果。
    • 注意: 内连接不写连接条件会出现笛卡尔积的结果,应该避免这种情况,而外连接不写连接条件会报错
    • select * from emp natural join dept;
    • select * from emp NATURAL left join dept;
    • select * from emp NATURAL right join dept;

<3> 子查询 (ANY子查询、IN子查询、SOME子查询、ALL子查询)

  • 子查询解决的问题:

    • 谁的薪资比张三高
      • select sal from emp where ename='张三'
  • 定义

    • 子查询允许把一个查询嵌套在另一个查询当中
    • 子查询又叫做内部查询,相当于内部查询,包含内部查询的就成为外部查询,子查询的结果被主查询所使用。
  • 注意的问题:

    • 括号

    • 可以在主查询的where select having from 后面,都可以使用子查询

    • 不可以在group by 后面使用子查询

    • 主查询和子查询可以不是同一张表;只有子查询返回的值,主查询可以使用 需求:查询部门名称是人力部的员工信息 -- 第一种方式:利用子查询 select * from emp where deptno=(select deptno from dept where dname='人力部') -- 第二种方式:利用关联查询 select * from emp e, dept d where e.deptno = d.deptno and d.dname = '人力部';

        SQL优化: 尽量使用多表查询
                 绝大部分的子查询在最终执行的时候都是转换成一个多表查询来执行的。 通过SQL的执行计划可以看出来
                 通过SQL执行计划会发现两种方式执行的一样的。
      
    • from 后面的子查询 需求: 查询员工号 姓名 薪资 select empno, ename, sal from emp;

    • 一般不在子查询中进行排序

    • 一般先执行子查询,再去执行主查询

ANY 关键字

假设any内部的查询返回结果个数是三个,如: result1, result2, result3, 那么
select .... from .... where a > any(....)
->
select .... from .... where a > result1 or a > result2 or a > result3

需求:
    查询工资比1号部门中任意一个员工高的员工信息
    select * from emp where sal > any(select sal from emp where deptno = 1);

ALL 关键字

  • ALL 关键字与 ANY 关键字类似,只不过把上面的or 改成 and

      select .... from .... where a > all(....)
      ->
      select .... from .... where a > result1 and a > result2 and a > result3
    
      需求:
          查询工资比1号部门中所有员工高的员工信息
      select * from emp where sal > any(select sal from emp where deptno = 1);
      select * from emp where sal > all(select sal from emp where deptno = 1);
    

SOME 关键字

some 关键字和 any 关键字是一样的功能,所以:
select .... from .... where a > any(....)
->
select .... from .... where a > result1 or a > result2 or a > result3

IN 关键字

In 运算符用于where 表达式中,以列表项的形式支持多个选择,语法如下:
    where column in (v1, v2, v3 ....);
    where column not in (v1, v2, v3 ....);
    当in 前面加上not 运算符时,表示与in 相反的意思,即不在这些列表项中选择。
    

案例:
    查询部门名称是人力部和研发部的员工
select * from emp where deptno in (select deptno from dept where dname = '人力部' or dname = '研发部');
点赞
收藏
评论区
推荐文章
Easter79 Easter79
2年前
sql多表连接查询
本文主要列举两张和三张表来讲述多表连接查询。新建两张表:表1:student 截图如下:!SQL多表连接查询(详细实例)_新客网(http://static.oschina.net/uploads/img/201406/12160627_gvI7.jpg)表2:course 截图如下:!SQL多表连接查询(详细实例)_
Kevin501 Kevin501
3年前
Mysql 多表联合查询效率分析及优化
Mysql多表联合查询效率分析及优化一、总结一句话总结:连表操作时:先根据查询条件和查询字段确定驱动表,确定驱动表之后就可以开始连表操作了,然后再在缓存结果中根据查询条件找符合条件的数据1、找出所有在左表,不在右表的纪录?我们可以用右表没有on匹配则显示null的规律,来找出所
Wesley13 Wesley13
2年前
HQL的多表查询
对象之间总是有各种各样的关系,关联关系是类之间最常见的关系。多表查询是HQL中的强大功能之一,包括内连接、左连接和右连接等。多表查询的设置及运行都比较麻烦,在运行本节中的示例时,务必保证每一步都没有错误。 6.4.1 表之间的关联关系 在数据库joblog中用到了3个表:student(学生表)、course(课程表
Wesley13 Wesley13
2年前
mysql数据库查询操作
\mysql数据库\知识要点:1\.单表查询2\.子查询3\.联表查询4\.事务在进行查询之前,我们要先建好关系表,并往数据表中插入些数据。为查询操作做好准备。\五张关系表的创建:\\\mysql创建并进入数据库:mysqlCREATEDATABASE\
Wesley13 Wesley13
2年前
MySQL之单表查询、多表查询
一、单表查询:单个表的查询方法及语法顺序需要通过实际例子来熟悉先将表数据创建下:!(https://oscimg.oschina.net/oscnet/592bec60479a16b20056327b683c142abe9.jpg)!(https://oscimg.oschina.net/
Wesley13 Wesley13
2年前
6.多表查询
多表查询本节重点:多表连接查询符合条件连接查询子查询准备工作:准备两张表,部门表(department)、员工表(employee)createtabledepartment(idint,namevarchar(20));
Wesley13 Wesley13
2年前
MySQL之多表查询
阅读目录一多表联合查询二多表连接查询三复杂条件多表查询四子语句查询五其他方式查询六 SQL逻辑查询语句执行顺序(重点)七外键约束八其他约束类型九表与表之间的关系一.多表联合查询!
Wesley13 Wesley13
2年前
Hibernate常见知识汇总
1.在数据库中条件查询速度很慢的时候,如何优化?1.建索引2.减少表之间的关联3.优化sql,尽量让sql很快定位数据,不要让sql做全表查询,应该走索引,把数据量大的表排在前面4.简化查询字段,没用的字段不要,已经对返回结果的控制,尽量返回少量数据2.在Hibernate中进行多表查询,每个表中各取几个字段,也就是说查询出来的结果
Wesley13 Wesley13
2年前
mysql 数据操作 多表查询 准备
为什么需要多表查询:因为我们不可能把所有数据都放在一张表里我们把不同数据存储放在一张一张不同表方便管理,但我们为了方便管理,把数据拆分到一张一张表去存储。但是数据还是一个整体,数据之间是有关联关系,那就要把分散的数据,合并到一起进行查询多表查询概念:连表操作通过连接方式,把有关系的表拼成一个整体,进行关联查询。
Wesley13 Wesley13
2年前
mysql减少join的几种通用方法
1关于join只要参与过后台开发,必然都对join有一定的了解.我们使用join查询,主要为满足两方面的需求:No.需求说明典型相似操作效果对比1查询关联表内容,如主从表之间内容子查询不考虑索引的情况下,join查询效率一般优于前者;即使考虑索引,多数情况子查询的索引并不好设计2多表关系限制in