MySQL聚合查询实现多表查询,联合查询,合并查询

Author:老九
计算机专业
可控之事 沉重冷静 不可控之事 乐观面对
85180586@qq.com
😄 😆 😵 😭 😰 😅 😢 😤 😍 ☺️ 😎 😩

👍 👎 💯 👏 🔔 🎁 ❓ 💣 ❤️ ☕️ 🌀 🙇 💋 🙏 💦 💩 ❗️ 💢
————————————————
版权声明:本文为CSDN博主「浦上青天」的原创文章


知识点

聚合查询

COUNT

count 就是计算行的值,不算 null,这里查询的是有多少行:

select count(*) from exam_result;

在这里插入图片描述

mysql> select * from emp;
+----+---------+-----------+---------+
| id | name    | role      | salary  |
+----+---------+-----------+---------+
|  1 | 丫丫1   | 老师      |  200.00 |
|  2 | 丫丫2   | 老师      |  300.00 |
|  3 | 丫丫3   | 老师      |  400.00 |
|  4 | 丫丫4   | 老师      |  500.00 |
|  5 | 丫丫5   | 老师      |  600.00 |
|  6 | 丫丫6   | 班主任    |  700.00 |
|  7 | 丫丫7   | 班主任    |  800.00 |
|  8 | 丫丫8   | 教导员    |  900.00 |
|  9 | 丫丫9   | 教导员    | 1000.00 |
+----+---------+-----------+---------+
9 rows in set (0.01 sec)
//查询id有多少行
mysql> select count(id) from emp;
+-----------+
| count(id) |
+-----------+
|         9 |
+-----------+
1 row in set (0.01 sec)

SUM

  • 把这一列的若干行相加 也不算 null 只能针对数字进行运算,不能对字符串进行运算。
mysql> select sum(salary) from emp;
+-------------+
| sum(salary) |
+-------------+
|     5400.00 |
+-------------+
1 row in set (0.00 sec)

聚合函数是可以搭配 where 来使用的。就是先执行筛选,后执行求和:

select sum(english) from exam_result where english > 70;

这里求的就是英语 > 70 的和,运行结果如下:
在这里插入图片描述

AVG

  • 返回查询到的数据的平均值
mysql> select avg(salary) from emp;
+-------------+
| avg(salary) |
+-------------+
|  600.000000 |
+-------------+
1 row in set (0.00 sec)

MAX

  • 返回查询到的数据的最大值
mysql> select max(salary) from emp;
+-------------+
| max(salary) |
+-------------+
|     1000.00 |
+-------------+
1 row in set (0.00 sec)

MIN

  • 返回查询到的数据的最小值
mysql> select min(salary) from emp;
+-------------+
| min(salary) |
+-------------+
|      200.00 |
+-------------+
1 row in set (0.00 sec)

GROUP BY 语句

group by 就是先分组,然后在针对每个组来使用聚合函数。先创建一个表,然后插入数据:

create table emp(
                    id int primary key auto_increment,
                    name varchar(20) not null,
                    role varchar(20) not null,
                    salary numeric(11,2)
);
insert into emp(name, role, salary) values
                                        ('A','服务员', 1000.20),
                                        ('B','游戏陪玩', 2000.99),
                                        ('C','游戏角色', 999.11),
                                        ('D','游戏角色', 333.5),
                                        ('E','游戏角色', 700.33),
                                        ('F','董事长', 12000.66);

在这里插入图片描述
通过 group by 分组,这里来查询不同角色对应的 sum,min,avg 的值。代码如下:

select role,max(salary),min(salary),avg(salary) from emp group by role;

在这里插入图片描述

HAVING 语句

where:对分组前的数据进行操作。例如:求平均工资的时候,去掉 E 求的结果就不包含 E 的数据了,代码如下:

select role, avg(salary) from emp where name != 'E' group by role;

在这里插入图片描述
having:对分组之后的数据进行操作。例如:求平均工资,然后再筛选。代码如下:

select role, avg(salary) from emp group by role having avg(salary < 10000);

这里的意思就是先求到平均工资,然后再筛选出平均工资小于 10000 的。运行结果如下:
在这里插入图片描述

联合查询

笛卡尔积

  • 实际开发中,往往数据来自不同的表,所以需要多表联合查询。笛卡尔积是多表查询的核心操作。
  • 笛卡尔积计算过程:先拿第一张表的第一条记录,和第二张表的每个记录,分别组合,得到一组新的记录。然后再拿第一张表的第二条记录,和第二张表的每条记录,分别组合,又得到新的记录,最终得到的记录就是笛卡尔积。针对两张表计算笛卡尔积,笛卡尔积的列数,就是 A 的列数 + B 的列数。笛卡尔积的行数,就是 A 的行数 * B 的行数。
  • 笛卡尔积用法:select * from 后面跟上多个表名,表名之间用逗号隔开。
  • 两张表中都有 班级Id 这一列,班级Id 的值。班级Id 就是连接条件。如果笛卡尔积的两个列名相同,在写条件的时候,就可以通过 表名.列名 的方式来访问。如果列不会混淆,就可以省略表名。代码如下:
select student.name, class.name from student, class where student.classId = class.classId;

数据构造

drop table if exists classes;
drop table if exists student;
drop table if exists course;
drop table if exists score;

create table classes (id int primary key auto_increment, name varchar(20), `desc` varchar(100));

create table student (id int primary key auto_increment, sn varchar(20),  name varchar(20), qq_mail varchar(20) ,
        classes_id int);

create table course(id int primary key auto_increment, name varchar(20));

create table score(score decimal(3, 1), student_id int, course_id int);

insert into classes(name, `desc`) values 
('计算机系2019级1班', '学习了计算机原理、C和Java语言、数据结构和算法'),
('中文系2019级3班','学习了中国传统文学'),
('自动化2019级5班','学习了机械自动化');

insert into student(sn, name, qq_mail, classes_id) values
('09982','黑旋风李逵','xuanfeng@qq.com',1),
('00835','菩提老祖',null,1),
('00391','白素贞',null,1),
('00031','许仙','xuxian@qq.com',1),
('00054','不想毕业',null,1),
('51234','好好说话','say@qq.com',2),
('83223','tellme',null,2),
('09527','老外学中文','foreigner@qq.com',2);

insert into course(name) values
('Java'),('中国传统文化'),('计算机原理'),('语文'),('高阶数学'),('英文');

insert into score(score, student_id, course_id) values
-- 黑旋风李逵
(70.5, 1, 1),(98.5, 1, 3),(33, 1, 5),(98, 1, 6),
-- 菩提老祖
(60, 2, 1),(59.5, 2, 5),
-- 白素贞
(33, 3, 1),(68, 3, 3),(99, 3, 5),
-- 许仙
(67, 4, 1),(23, 4, 3),(56, 4, 5),(72, 4, 6),
-- 不想毕业
(81, 5, 1),(37, 5, 5),
-- 好好说话
(56, 6, 2),(43, 6, 4),(79, 6, 6),
-- tellme
(80, 7, 2),(92, 7, 6);

内连接

在这里插入图片描述

  • 使用内连接的思路
    1.观察要查询的数据涉及到几张表
    2.多张表连接时使用的是笛卡尔积运算,所以会产生许多无用的数据,此时我们就应该加上表的连接条件去除掉无用的数据
    3.再用选择条件和字段去控制得到的数据表为我们所需要的
-- 查询许仙同学的成绩
mysql> select student.name,score.score from student,score where student.id = score.student_id and student.name = '许仙';
+--------+-------+
| name   | score |
+--------+-------+
| 许仙   |  67.0 |
| 许仙   |  23.0 |
| 许仙   |  56.0 |
| 许仙   |  72.0 |
+--------+-------+
4 rows in set (0.00 sec)

-- 和上面是等价的(from 表1 join 表2 on 条件 )
mysql> select student.name,score.score from student join score on student.id = score.student_id and student.name = '许仙';
+--------+-------+
| name   | score |
+--------+-------+
| 许仙   |  67.0 |
| 许仙   |  23.0 |
| 许仙   |  56.0 |
| 许仙   |  72.0 |
+--------+-------+
4 rows in set (0.00 sec)

-- 查询所有同学的总成绩
mysql> select student.name , sum(score.score) as total from student,score where student.id = score.student_id group by student.id;
+-----------------+-------+
| name            | total |
+-----------------+-------+
| 黑旋风李逵      | 300.0 |
| 菩提老祖        | 119.5 |
| 白素贞          | 200.0 |
| 许仙            | 218.0 |
| 不想毕业        | 118.0 |
| 好好说话        | 178.0 |
| tellme          | 172.0 |
+-----------------+-------+
7 rows in set (0.00 sec)

-- 查询所有同学的总成绩,及同学的个人信息
mysql> select student.name,course.name,score.score from student,score,course where student.id = score.student_id and course.id = score.course_id;
+-----------------+--------------------+-------+
| name            | name               | score |
+-----------------+--------------------+-------+
| 黑旋风李逵      | Java               |  70.5 |
| 黑旋风李逵      | 计算机原理         |  98.5 |
| 黑旋风李逵      | 高阶数学           |  33.0 |
| 黑旋风李逵      | 英文               |  98.0 |
| 菩提老祖        | Java               |  60.0 |
| 菩提老祖        | 高阶数学           |  59.5 |
| 白素贞          | Java               |  33.0 |
| 白素贞          | 计算机原理         |  68.0 |
| 白素贞          | 高阶数学           |  99.0 |
| 许仙            | Java               |  67.0 |
| 许仙            | 计算机原理         |  23.0 |
| 许仙            | 高阶数学           |  56.0 |
| 许仙            | 英文               |  72.0 |
| 不想毕业        | Java               |  81.0 |
| 不想毕业        | 高阶数学           |  37.0 |
| 好好说话        | 中国传统文化       |  56.0 |
| 好好说话        | 语文               |  43.0 |
| 好好说话        | 英文               |  79.0 |
| tellme          | 中国传统文化       |  80.0 |
| tellme          | 英文               |  92.0 |
+-----------------+--------------------+-------+
20 rows in set (0.00 sec)

--和上面等价 from 表1 join 表2 on 条件 join 表3 on 条件
mysql> select student.name,course.name,score.score from student join score on student.id = score.student_id join course on score.course_id = course.id;
+-----------------+--------------------+-------+
| name            | name               | score |
+-----------------+--------------------+-------+
| 黑旋风李逵      | Java               |  70.5 |
| 黑旋风李逵      | 计算机原理         |  98.5 |
| 黑旋风李逵      | 高阶数学           |  33.0 |
| 黑旋风李逵      | 英文               |  98.0 |
| 菩提老祖        | Java               |  60.0 |
| 菩提老祖        | 高阶数学           |  59.5 |
| 白素贞          | Java               |  33.0 |
| 白素贞          | 计算机原理         |  68.0 |
| 白素贞          | 高阶数学           |  99.0 |
| 许仙            | Java               |  67.0 |
| 许仙            | 计算机原理         |  23.0 |
| 许仙            | 高阶数学           |  56.0 |
| 许仙            | 英文               |  72.0 |
| 不想毕业        | Java               |  81.0 |
| 不想毕业        | 高阶数学           |  37.0 |
| 好好说话        | 中国传统文化       |  56.0 |
| 好好说话        | 语文               |  43.0 |
| 好好说话        | 英文               |  79.0 |
| tellme          | 中国传统文化       |  80.0 |
| tellme          | 英文               |  92.0 |
+-----------------+--------------------+-------+
20 rows in set (0.00 sec)

外连接

左外连接

在这里插入图片描述

  • 联合查询,左侧的表完全显示我们就说是左外连接
  • select 列 from 表1 left join 表2 on 条件
  • 以左侧的表为主,会尽可能的把左侧的表的记录都列出来,大不了后侧的表对应列填成NULL
mysql> create table student(id int, name varchar(20),classId int);
Query OK, 0 rows affected (0.01 sec)

mysql> create table class(id int,name varchar(20));
Query OK, 0 rows affected (0.02 sec)

mysql> insert into student values(1,'张三',1);
Query OK, 1 row affected (0.01 sec)

mysql> insert into student values(2,'李四',1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into student values(3,'王五',2);
Query OK, 1 row affected (0.00 sec)

mysql> insert into student values(4,'赵六',3);
Query OK, 1 row affected (0.00 sec)

mysql> select * from student;
+------+--------+---------+
| id   | name   | classId |
+------+--------+---------+
|    1 | 张三   |       1 |
|    2 | 李四   |       1 |
|    3 | 王五   |       2 |
|    4 | 赵六   |       3 |
+------+--------+---------+
4 rows in set (0.00 sec)

mysql> insert into class values(1,'java100');
Query OK, 1 row affected (0.00 sec)

mysql> insert into class values(2,'java101');
Query OK, 1 row affected (0.00 sec)

mysql> select * from class;
+------+---------+
| id   | name    |
+------+---------+
|    1 | java100 |
|    2 | java101 |
+------+---------+
2 rows in set (0.00 sec)

mysql> select * from student,class where student.classId = class.id;
+------+--------+---------+------+---------+
| id   | name   | classId | id   | name    |
+------+--------+---------+------+---------+
|    1 | 张三   |       1 |    1 | java100 |
|    2 | 李四   |       1 |    1 | java100 |
|    3 | 王五   |       2 |    2 | java101 |
+------+--------+---------+------+---------+
3 rows in set (0.00 sec)

mysql> select * from student left join class on student.classId = class.id;
+------+--------+---------+------+---------+
| id   | name   | classId | id   | name    |
+------+--------+---------+------+---------+
|    1 | 张三   |       1 |    1 | java100 |
|    2 | 李四   |       1 |    1 | java100 |
|    3 | 王五   |       2 |    2 | java101 |
|    4 | 赵六   |       3 | NULL | NULL    |
+------+--------+---------+------+---------+
4 rows in set (0.00 sec)

右外连接

在这里插入图片描述

  • select 列 from 表1 right join 表2 on 条件
mysql> create table student(id int,name varchar(20));
Query OK, 0 rows affected (0.01 sec)

mysql> create table score(student_id int,score int);
Query OK, 0 rows affected (0.01 sec)

mysql> insert into student values(1,'张三');
Query OK, 1 row affected (0.00 sec)

mysql> insert into student values(2,'李四');
Query OK, 1 row affected (0.00 sec)

mysql> insert into student values(3,'王五');
Query OK, 1 row affected (0.00 sec)

mysql> insert into score values(1,90),(2,80),(4,70);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from student;
+------+--------+
| id   | name   |
+------+--------+
|    1 | 张三   |
|    2 | 李四   |
|    3 | 王五   |
+------+--------+
3 rows in set (0.00 sec)

mysql> select * from score;
+------------+-------+
| student_id | score |
+------------+-------+
|          1 |    90 |
|          2 |    80 |
|          4 |    70 |
+------------+-------+
3 rows in set (0.00 sec)

mysql> select * from student join score on student.id = score.student_id;
+------+--------+------------+-------+
| id   | name   | student_id | score |
+------+--------+------------+-------+
|    1 | 张三   |          1 |    90 |
|    2 | 李四   |          2 |    80 |
+------+--------+------------+-------+
2 rows in set (0.00 sec)

mysql> select * from student left join score on student.id = score.student_id;
+------+--------+------------+-------+
| id   | name   | student_id | score |
+------+--------+------------+-------+
|    1 | 张三   |          1 |    90 |
|    2 | 李四   |          2 |    80 |
|    3 | 王五   |       NULL |  NULL |
+------+--------+------------+-------+
3 rows in set (0.00 sec)

mysql> select * from student right join score on student.id = score.student_id;
+------+--------+------------+-------+
| id   | name   | student_id | score |
+------+--------+------------+-------+
|    1 | 张三   |          1 |    90 |
|    2 | 李四   |          2 |    80 |
| NULL | NULL   |          4 |    70 |
+------+--------+------------+-------+
3 rows in set (0.00 sec)

子查询

  • 在一个查询语句里套用查询语句称为子查询

单行子查询

  • 子查询返回一条结果
-- 查找“不想毕业”同学的同班同学
mysql> select name from student where classes_id = (select classes_id from student where name = "不想毕业");
+-----------------+
| name            |
+-----------------+
| 黑旋风李逵      |
| 菩提老祖        |
| 白素贞          |
| 许仙            |
| 不想毕业        |
+-----------------+
5 rows in set (0.00 sec)

多行子查询(IN)

返回多行记录的子查询,要把=换成in

//查询“语文”或“英文”课程的成绩信息
mysql> select * from score where course_id in(select id from course where name='语文'or name = '英文');
+-------+------------+-----------+
| score | student_id | course_id |
+-------+------------+-----------+
|  98.0 |          1 |         6 |
|  72.0 |          4 |         6 |
|  43.0 |          6 |         4 |
|  79.0 |          6 |         6 |
|  92.0 |          7 |         6 |
+-------+------------+-----------+
5 rows in set (0.00 sec)

合并查询(union)

  • 把多个查询语句的结果合并到一起,合并的前提是两个sql查询的列是对应的
mysql> select * from course where name = '英文' union select * from course where id < 3;
+----+--------------------+
| id | name               |
+----+--------------------+
|  6 | 英文               |
|  1 | Java               |
|  2 | 中国传统文化       |
+----+--------------------+
3 rows in set (0.00 sec)

也可以使用 or 实现,不过使用 or 的时候必须保证是针对同一个表来进行操作的。代码如下:

select * from course where name = '英文' or id < 3;

在这里插入图片描述

先赞后看,养成习惯!!!^ _ ^♥♥♥
每天都更新知识点哦!!!
码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘记关注我哦!

评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李小浦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值