一、连接查询[连表查询、多表查询]

当查询结果的列来源于多张表时,需要将多张表连接成一个大的数据集,再选择合适的列返回

mysql支持三种类型的连接查询,分别为:

内连接查询(inner join)

查询的结果为两个表匹配到的数据

使用内连接,必须保证两个表都会对应id的数据才会被查询出来。

格式:select 字段1,字段2... from 主表A inner join 从表B on 主表A.主键=从表B.外键

例如:查询学生的信息[ 成绩、名字、班级 ]        我们给学生表添加一个学生信息,然后使用该学生的主键id来连表查询成绩、名字和班级。

insert into student (name,sex,age,class,description) values ('刘德华',1,17,406,'');

select achievement,name,class
from student as a
inner join achievement as b
on a.id=b.sid
where id=101; # 上面语句因位该学生只在学生表student中有数据,而成绩表中没有数据,所以使用内连接,连表查询的结果是
Empty set (0.00 sec)

同样,如果从表有数据,而主表没有数据,则使用内连接查询一样无法查询到结果。

#例如,添加一个成绩记录,是不存在学生
insert into achievement (sid,cid,achievement) values (102,10,85); select achievement,name,class
from student as a
inner join achievement as b
on a.id=b.sid
where id=102;

右连接查询(right join)

只要从表有数据,不管主表是否有数据,都会查询到结果。[以从表的结果为主 例如:a.id=b.sid,只要b表的sid存在就可以 ;  a.id不存在不要紧  左表中不存在的数据使用null填充]

查询的结果为两个表匹配到的数据,右表特有的数据,对于左表中不存在的数据使用null填充

格式:select 字段1,字段2... from 主表 right join 从表 on 主表.主键=从表.外键

select achievement,name,class from student as a
right join achievement as b
on a.id=b.sid
where b.sid=102;

左连接查询(left join)

只要主表有数据,不管从表是否有数据都会被查询出来。

查询的结果为两个表匹配到的数据,左表特有的数据,对于右表中不存在的数据使用null填充

    

格式:select * from 表1 left join 表2 on 表1.列 = 表2.列

例如,使用左连接查询学生表与成绩表,查询学生姓名及分数

select achievement,name,class
from student as a
left join achievement as b
on a.id=b.sid;
等同于
select achievement,name,class
from achievement as b
right join student as a
on a.id=b.sid;

总结:三种连表查询,最常用的是 left join,然后inner join保证数据的一致性。右连接基本上都是使用左连接代替。

select 表.字段1,表.字段2,表.字段3.....
from 主表
left join 从表1 on 主表.主键=从表1.外键
left join 从表2 on 主表.主键=从表2.外键
# 这里和从表2连接的on条件看实际情况,也会出现从表1.主键=从表2.外键的情况
left join 从表3 on 主表.主键=从表3.外键
# 这里可以是(从表1或从表2).主键=从表2.外键的情况
left join ...

多表关联格式

多表查询的效率,性能比单表要差。

多表查询以后,还会带来字段多了会引起字段覆盖的情况、

主表student      从表1 achievement   从表2 course

 name                 xxx                              name

上面三张表如果连表,则出现主表的name覆盖从表2的name这种情况。

上面两个问题:

1. 把多表查询语句可以替换成单表查询语句【需要优化的情况】
2. 把重复的字段名,分别使用as来设置成别的名称。

多表查询的缺点

练习:

select sum(b.achievement) sum   # 有时候as可以不写
from student as a
left join achievement as b on a.id=b.sid
where a.id=20;

查询id为20的学生的考试总分.

1. 先查305的学生信息
2. 再查305的学生成绩
3. 再查305的学生成绩对应的课程
4. 最后查305的学生成绩对应的课程的老师
select a.name,b.achievement,c.course,d.name
from student as a
left join achievement as b on a.id=b.sid
left join course as c on b.cid=c.id
left join lecturer as d on d.id=c.lecturer_id
where a.class=305;

查询305班级所有学生的课程名称、课程成绩、以及对应课程的授课老师。

上面代码的效果:
+--------+-------------+----------------+--------+
| name | achievement | course | name |
+--------+-------------+----------------+--------+
| 谭季同 | 100.0 | Photoshop | 唐老师 |
| 谭季同 | 79.0 | 负载均衡 | 杜老师 |
| 谭季同 | 78.5 | Flask项目 | 白老师 |
| 白瀚文 | 73.0 | go | 陈老师 |
| 白瀚文 | 65.0 | webpy | 林老师 |
| 白瀚文 | 86.0 | 数据分析 | 郑老师 |
| 白瀚文 | 60.0 | API接口 | 宋老师 |
| 晁然 | 0.0 | Flask | 陈老师 |
| 晁然 | 78.0 | Python网络编程 | 江老师 |
| 晁然 | 78.0 | HTML5 | 丘老师 |
| 白素欣 | 81.0 | Django项目 | 易老师 |
| 白素欣 | 90.0 | Python | 黄老师 |
| 白素欣 | 39.0 | Nginx | 曹老师 |
| 庄晓敏 | 82.5 | Nginx | 曹老师 |
| 庄晓敏 | 68.0 | Python | 黄老师 |
| 庄晓敏 | 100.0 | API接口 | 宋老师 |
+--------+-------------+----------------+--------+

上面代码的效果:

二、单表的连表查询[自关联查询]

核心就是把一张表看做2张表来操作

# 建表:
create table area(
id smallint not null auto_increment comment '主键ID',
name char(30) not null comment '地区名称',
pid smallint not null default 0 comment '父级地区ID',
primary key (id)
) engine=innodb charset=utf8; insert into area (name,pid) values ('广东',0),('深圳',1),('龙岗',2),('福田',2),('宝安',2);

格式:select 字段1,字段2...from 主表(当前表) as a  left join 从表(当前表) as b on a.主键=b.外键

# 主表看成保存深圳的表,
# 从表看成保存深圳子地区的表 select b.id,b.name
from area as a
left join area as b on a.id=b.pid
where a.name='深圳';

查找深圳地区的子地区,SQL代码:

 

三、子查询

在一个 select 语句中,嵌入了另外一个 select 语句, 那么被嵌入的 select 语句称之为子查询语句

格式:select 字段 from 表名 where 条件(另一条查询语句)

主查询

主要查询的对象,第一条 select 语句

主查询和子查询的关系

  • 子查询是嵌入到主查询中

  • 子查询是辅助主查询的,要么充当条件,要么充当数据源

  • 子查询是可以独立存在的语句,是一条完整的 select 语句

##### 例如:查询406班上大于平均年龄的学生

使用 子查询:

1. 查询406班学生平均年龄
2. 查询大于平均年龄的学生 查询406班级学生的平均身高
select name,age from student where age > (select avg(age) as avg from student where class=406) and class=406;

例如:查询406班上大于平均年龄的学生

having

group by 字段 having 条件;

过滤筛选,主要作用类似于where关键字,用于在SQL语句中进行条件判断,过滤结果的。

但是与where不同的地方在于having只能跟在group by 之后使用。

练习:查询301班级里的学生的平均成绩大于班上平均成绩的学生成绩信息(name,平均分,班级)。

# 先求301班的平均成绩
select avg(achievement) as achi from student as a
left join achievement as b on a.id=b.sid
where class=301; # 判断301中的每个人平均成绩大于上面的到的平均成绩
select name,avg(achievement) from student as a
left join achievement as b on a.id=b.sid
where class=301 group by name having avg(achievement) > (select avg(achievement) as achi from student as a
left join achievement as b on a.id=b.sid
where class=301);
mysql> select avg(achievement) as achi from student as a
left join achievement as b on a.id=b.sid
where class=301;
+----------+
| achi |
+----------+
| 68.96875 |
+----------+
1 row in set mysql> select name,
achievement from student as a
left join achievement as b on a.id=b.sid
where class=301;
+--------+-------------+
| name | achievement |
+--------+-------------+
| 程星云 | 63.5 |
| 程星云 | 72 |
| 程星云 | 40.5 |
| 娄镇明 | 86.5 |
| 娄镇明 | 85.5 |
| 柳宗仁 | 99 |
| 柳宗仁 | 60 |
| 曾嘉慧 | 90 |
| 王紫伊 | 73 |
| 王紫伊 | 0 |
| 王紫伊 | 55 |
| 黄威 | 98 |
| 黄威 | 79 |
| 黄威 | 62.5 |
| 庄信杰 | 60 |
| 庄信杰 | 79 |
+--------+-------------+
16 rows in set mysql> select sum(achievement)
from student as a
left join achievement as b on a.id=b.sid
where class=301;
+------------------+
| sum(achievement) |
+------------------+
| 1103.5 |
+------------------+
1 row in set mysql> select count
(achievement) from student as a
left join achievement as b on a.id=b.sid
where class=301;
+--------------------+
| count(achievement) |
+--------------------+
| 16 |
+--------------------+
1 row in set mysql> select name,avg(achievement) from student as a
left join achievement as b on a.id=b.sid
where class=301 group by name having avg(achievement) > (select avg(achievement) as achi from student as a
left join achievement as b on a.id=b.sid
where class=301);
+--------+------------------+
| name | avg(achievement) |
+--------+------------------+
| 娄镇明 | 86 |
| 庄信杰 | 69.5 |
| 曾嘉慧 | 90 |
| 柳宗仁 | 79.5 |
| 黄威 | 79.83333 |
+--------+------------------+
5 rows in set mysql>

结果

select查询语句的完整格式

select distinct 字段1,字段2....
from 表名 as 表别名
left join 从表1 on 表名.主键=从表1.外键
left join ....
where ....
group by ... having ...
order by ...
limit start,count
  • 执行顺序为:

    • from 表名[包括连表]

    • where ....

    • group by ...

    • select distinct *

    • having ...

    • order by ...

    • limit start,count

  • 实际使用中,只是语句中某些部分的组合,而不是全部

MySql数据库多表操作的更多相关文章

  1. 数据库-mysql数据库和表操作

    一:数据库查询增加删除 1)mysql数据库查询:show databases MariaDB [mysql]> show databases; +--------------------+ | ...

  2. mysql数据库之表操作及字段约束条件

    目录 一.存储引擎 二.表介绍 三.创建表 四.查看表结构 五.数据类型 一.介绍 二.数值类型 整数类型 浮点型 三.字符串类型 四.日期类型 五.枚举类型与集合类型 六.约束条件 七.修改表 al ...

  3. MySQL快速回顾:数据库和表操作

    前提要述:参考书籍<MySQL必知必会> 利用空闲时间快速回顾一些数据库基础. 4.1 连接 在最初安装MySQL,可能会要求你输入一个管理登录(通常为root)和一个口令(密码). 连接 ...

  4. [MySQL数据库之表的详细操作:存储引擎、表介绍、表字段之数据类型]

    [MySQL数据库之表的详细操作:存储引擎.表介绍.表字段之数据类型] 表的详细操作 存储引擎 mysql中建立的库======>文件夹 库中建立的表======>文件 用来存储数据的文件 ...

  5. python爬取信息到数据库与mysql简单的表操作

    python 爬取豆瓣top250并导入到mysql数据库中 import pymysql import requests import re url='https://movie.douban.co ...

  6. python操作mysql数据库的相关操作实例

    python操作mysql数据库的相关操作实例 # -*- coding: utf-8 -*- #python operate mysql database import MySQLdb #数据库名称 ...

  7. linux系统上Mysql数据库导入导出操作

    需求:把MySQL数据库目录中的dz数据库备份到/home/dz_bak.sql ,然后再新建一个数据库dzbak,最后把/home/dz_bak.sql 导入到数据库dzbak中.操作如下:以下操作 ...

  8. MySQL数据库分表的3种方法

    原文地址:MySQL数据库分表的3种方法作者:dreamboycx 一,先说一下为什么要分表 当一张的数据达到几百万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了.分表的目 ...

  9. 【代码学习】MYSQL数据库的常见操作

    ---恢复内容开始--- ============================== MYSQL数据库的常见操作 ============================== 一.mysql的连接与 ...

随机推荐

  1. [bzoj4010][HNOI2015]菜肴制作_贪心_拓扑排序

    菜肴制作 bzoj-4010 HNOI-2015 题目大意:给定一张n个点m条边的有向图,求一个toposort,使得:(1)满足编号为1的点尽量在前:(2)满足(1)的情况下编号为2的点尽量在前,以 ...

  2. portmap 和 rpc程序

    Portmap 是为RPC 程序服务的. 每一个RPC server程序启动的时候要向portmap程序注册.这样portmap程序就知道这些RPC server监听在哪个端口. 而RPC clien ...

  3. spring 计时器

    spring 计时器 可以这样: http://blog.csdn.net/u010648555/article/details/52162840 也可以使用annotation <!-- 设置 ...

  4. android 用java代码设置布局、视图View的宽度/高度或自适应

    在achat项目中,对话内容的长宽设置为自适应.可是假设文本内容太多,则宽度几乎相同布满,若自己说的和对方说的都非常多内容.则满屏都是文字.则不easy分辨出是来自别人说的还是自己说的.那么须要对本身 ...

  5. 专业函数画图软件Origin

    首先:Origin软件已经是科研院所等单位的必备工作软件之中的一个,之所以大家讨论得较少,有可能并非其上手难度低.而是这些使用人群的学习理解能力要相对高一点吧: 其次:Excel不垃圾,但在函数画图方 ...

  6. 怎样使用OpenShare部署和运营企业门户

    怎样使用OpenShare部署和运营企业门户 这篇Blog是偏向企业内总体门户部署和运营的指南,是偏向总体管理和规划的.并非针对终端用户的OpenShare软件操作手冊,详细的操作能够上优酷看相关视频 ...

  7. WPF学习笔记——为BUTTON添加背景图片

    首先要肯定,代码: <Style x:Key="UserItemButton" TargetType="Button"> <Setter Pr ...

  8. App/Activity/Screen Orientation

    测试android屏幕方向的小Demo 1.首先我们在values下面新建文件arrays.xml(用来在下拉列表中显示) <?xml version="1.0" encod ...

  9. Android+Jquery Mobile学习系列(5)-SQLite数据库

    SQLite是轻量级的.嵌入式的.关系型数据库,目前已经在iPhone.Android等手机系统中使用,SQLite可移植性好,很容易使用,很小,高效而且可靠. 因为Android已经集成了SQLit ...

  10. Codeforces--630A--Again Twenty Five! (水题)

     Again Twenty Five! Time Limit: 500MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u ...