【MySQL表的增删改查】(进阶二)

📒查询

🥂聚合查询

前面的表达式查询,处理列与列的运算
而处理行与行之间的运算 需要用到聚合查询

🐳聚合函数

聚合函数中,如果遇到了NULL 就会跳过

函数说明
COUNT([DISTINCT] expr)返回查询到的数据的 数量
SUM([DISTINCT] expr)返回查询到的数据的 总和,不是数字没有意义
AVG([DISTINCT] expr)返回查询到的数据的 平均值,不是数字没有意义
MAX([DISTINCT] expr)返回查询到的数据的 最大值,不是数字没有意义
MIN([DISTINCT] expr)返回查询到的数据的 最小值,不是数字没有意义

案例:

INSERT INTO exam_result (id,name, chinese, math, english) VALUES
 (1,'唐三藏', 67, 98, 56),
 (2,'孙悟空', 87.5, 78, 77),
 (3,'猪悟能', 88, 98.5, 90),
 (4,'曹孟德', 82, 84, 67),
 (5,'刘玄德', 55.5, 85, 45),
 (6,'孙权', 70, 73, 78.5),
 (7,'宋公明', 75, 65, 30);

在这里插入图片描述

  • count
select count(*) from exam_result;
-- 此处就得到了结果的行数
-- 聚合函数的函数名和括号之间,不能有空格
-- 括号里面也可以写具体的列
-- 先查询,再聚合

在这里插入图片描述

注意点:
针对某一列进行查询的时候,就是在看这一列有多少个 非 NULL 的结果
而 select 则不关注 NULL
在这里插入图片描述
在这里插入图片描述

  • sum

求和:

-- 统计数学成绩总分
SELECT SUM(math) FROM exam_result;
-- 不及格 < 60 的总分,没有结果,返回 NULL
SELECT SUM(math) FROM exam_result WHERE math < 60;

在这里插入图片描述

  • avg
-- 统计平均总分
SELECT AVG(chinese + math + english) 平均总分 FROM exam_result;

在这里插入图片描述

  • max
-- 返回英语最高分
SELECT MAX(english) FROM exam_result;
  • min
-- 返回 > 70 分以上的数学最低分
SELECT MIN(math) FROM exam_result WHERE math > 70;

🍬 GROUP BY子句

SELECT 中使用 GROUP BY 子句可以对指定列进行分组查询。
需要满足:使用 GROUP BY 进行分组查询时,SELECT 指定的字段必须是“分组依据字段”,其他字段若想出现在SELECT 中则必须包含在聚合函数中。

-- 语法
select column1, sum(column2), .. from table group by column1,column3;

案例:

创建一张新表

  • 准备测试表及数据:职员表,有id(主键)、name(姓名)、role(角色)、salary(薪水)
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
('王','服务员', 1000.20),
('李','游戏陪玩', 2000.99),
('孙悟空','游戏角色', 999.11),
('猪无能','游戏角色', 333.5),
('沙和尚','游戏角色', 700.33),
('隔壁老王','董事长', 12000.66);
-- role岗位 可以按岗位进行分组
  • 查询每个角色的最高工资、最低工资和平均工资
select role,max(salary),min(salary),avg(salary) from emp group by role;

在这里插入图片描述

🍾HAVING(注意跟WHERE的使用)

GROUP BY 子句进行分组以后,需要对分组结果再进行条件过滤时,不能使用 WHERE 语句,而需要用HAVING

  • 显示平均工资低于1500的角色和它的平均工资
select role,max(salary),min(salary),avg(salary) from emp group by role 
having avg(salary)<1500;

🏀联合查询(多表查询)(重要)

实际开发中往往数据来自不同的表,所以需要多表联合查询。
列数:就是原来两个表列数之和
行数:就是原来两个表行数之积
多表查询是对多张表的数据取笛卡尔积:

在这里插入图片描述

注意:关联查询可以对关联表使用别名。

-- 创建班级表
create table class(
       classId int,
       className varchar(20)
);

-- 创建学生表
create table student(
       id int,
       name varchar(20),
       classId int
);

-- 插入数据
insert into class values (101,'java101'),(102,'java102');

insert into student values 
       (1,'张三',101),
       (2,'李四',101),
       (3,'王五',102),
       (4,'赵六',102);

在这里插入图片描述

-- 进行笛卡尔积操作
select * from student,class;

在这里插入图片描述

笛卡尔积是全排列过程,在尝试穷举出所有的可能性
存在一部分,无效数据 / 无意义的数据

  • 修改
select * from student,class where student.classId = class.classId;

在这里插入图片描述

  • 初始化测试数据
-- 创建表
CREATE TABLE classes (
 id INT PRIMARY KEY auto_increment,
 name VARCHAR(20),
 `desc` VARCHAR(100)
);
-- 插入信息
insert into classes(name, `desc`) values
('计算机系2019级1班', '学习了计算机原理、C和Java语言、数据结构和算法'),
('中文系2019级3班','学习了中国传统文学'),
('自动化2019级5班','学习了机械自动化');

-- 创建表
DROP TABLE IF EXISTS student;
CREATE TABLE student (
   id INT NOT NULL PRIMARY KEY,
   sn INT UNIQUE,
   name VARCHAR(20) DEFAULT 'unkown',
   qq_mail VARCHAR(20)
);
-- 插入信息
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);

-- 创建表
DROP TABLE IF EXISTS course;
CREATE TABLE course (
   id INT PRIMARY KEY auto_increment,
   name VARCHAR(20)
);
-- 插入信息
insert into course(name) values
('Java'),('中国传统文化'),('计算机原理'),('语文'),('高阶数学'),('英文');

--创建表
DROP TABLE IF EXISTS score;
CREATE TABLE score (
   id INT PRIMARY KEY auto_increment,
 score DECIMAL(3, 1),
   student_id int,
 course_id int,
 FOREIGN KEY (student_id) REFERENCES student(id),
 FOREIGN KEY (course_id) REFERENCES course(id)
);
-- 插入信息
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);

🐋内连接

在这里插入图片描述

语法:

select 字段 from1 别名1 [inner] join2 别名2 on 连接条件 and 其他条件;
select 字段 from1 别名1,2 别名2 where 连接条件  and 其他条件;

案例:

  • 查询“许仙”同学的 成绩
 select student.name,score.score 
 from 
        student,score 
 where 
        student.id = score.student_id 
 and 
        student.name = '许仙';
        
-- 还有另一种写法 join on
 select student.name,score.score 
 from 
        student join score on 
        student.id = score.student_id 
 and
        name = '许仙';
  • 查询所有同学的总成绩,及同学的个人信息(学生名字):
    在这里插入图片描述
select name,sum(score) 
from 
       student,score 
where 
       student.id = score.student_id 
group by
       student.name;

  • 查询所有同学的成绩,及同学的个人信息:
select student.name,course.name,score 
from 
       student,course,score 
where 
       student.id = score.student_id 
and 
       course.id= score.course_id;

-- 或者用 join on 
select student.name,course.name,score.score 
from 
       student join score on 
       student.id = score.student_id 
       join course on 
       course.id = score.course_id;

在这里插入图片描述

🍎外连接

外连接分为左外连接和右外连接。如果联合查询,左侧的表完全显示我们就说是左外连接;右侧的表完全显示我们就说是右外连接。

语法:

-- 左外连接,表1完全显示
select 字段名  from 表名1 left join 表名2 on 连接条件;
-- 右外连接,表2完全显示
select 字段 from 表名1 right join 表名2 on 连接条件;

在这里插入图片描述
在这里插入图片描述

  • 案例:查询所有同学的成绩,及同学的个人信息,如果该同学没有成绩,也需要显示
-- “老外学中文”同学 没有考试成绩,也显示出来了
select * from student stu left join score sco on stu.id=sco.student_id;
-- 对应的右外连接为:
select * from score sco right join student stu on stu.id=sco.student_id;
-- 学生表、成绩表、课程表3张表关联查询
SELECT
 stu.id,
 stu.sn,
 stu.NAME,
 stu.qq_mail,
 sco.score,
 sco.course_id,
 cou.NAME
FROM
 student stu
 LEFT JOIN score sco ON stu.id = sco.student_id
 LEFT JOIN course cou ON sco.course_id = cou.id
ORDER BY
 stu.id;

🏐自连接

自连接是指在同一张表连接自身进行查询.

  • 案例:
  • 显示所有“计算机原理”成绩比“Java”成绩高的成绩信息
-- 先查询“计算机原理”和“Java”课程的id
select id,name from course where name='Java' or name='计算机原理';
-- 再查询成绩表中,“计算机原理”成绩比“Java”成绩 好的信息
SELECT
 s1.* 
FROM
 score s1,
 score s2 
WHERE
 s1.student_id = s2.student_id
 AND s1.score < s2.score
 AND s1.course_id = 1
 AND s2.course_id = 3;
-- 也可以使用join on 语句来进行自连接查询
SELECT
 s1.* 
FROM
 score s1
 JOIN score s2 ON s1.student_id = s2.student_id
 AND s1.score < s2.score
 AND s1.course_id = 1
 AND s2.course_id = 3;
  • 以上查询只显示了成绩信息,并且是分布执行的。要显示学生及成绩信息,并在一条语句显示:
SELECT
 stu.*,
 s1.score Java,
 s2.score 计算机原理
FROM
 score s1
 JOIN score s2 ON s1.student_id = s2.student_id
 JOIN student stu ON s1.student_id = stu.id
 JOIN course c1 ON s1.course_id = c1.id
 JOIN course c2 ON s2.course_id = c2.id
 AND s1.score < s2.score
 AND c1.NAME = 'Java'
 AND c2.NAME = '计算机原理';
  • 也可以只显示一个同学的信息
select * from 
       score as s1,score as s2 
where 
       s1.student_id = s2.student_id 
and 
       s1.course_id = 3 
and 
       s2.course_id = 1 
and 
       s1.score > s2.score;

在这里插入图片描述

✨子查询

子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询

  • 单行子查询:返回一行记录的子查询
    查询与“不想毕业” 同学的同班同学:
select * 
from 
       student 
where 
       classes_id=(
select classes_id from student where name='不想毕业'
);
  • 多行子查询:返回多行记录的子查询
  • 案例:查询“语文”或“英文”课程的成绩信息
  • [NOT] IN关键字:
-- 使用IN
select * from score where course_id in (select id from course where
name='语文' or name='英文');
-- 使用 NOT IN
select * from score where course_id not in (select id from course where
name!= '语文' and name!='英文');

  • 可以使用多列包含:
-- 插入重复的分数:score, student_id, course_id列重复
insert into score(score, student_id, course_id) values
-- 黑旋风李逵
(70.5, 1, 1),(98.5, 1, 3),
-- 菩提老祖
(60, 2, 1);
-- 查询重复的分数
SELECT
 * 
FROM
 score 
WHERE
 ( score, student_id, course_id ) IN ( SELECT score, student_id, 
course_id FROM score GROUP BY score, student_id, course_id HAVING
count( 0 ) > 1 );
  • [NOT] EXISTS关键字:
-- 使用 EXISTS
select * from score sco where exists (select sco.id from course cou 
where (name='语文' or name='英文') and cou.id = sco.course_id);
-- 使用 NOT EXISTS
select * from score sco where not exists (select sco.id from course cou 
where (name!='语文' and name!='英文') and cou.id = sco.course_id);

🍾合并查询

在实际应用中,为了合并多个select的执行结果,可以使用集合操作符 union,union all。使用UNION和UNION ALL时,前后查询的结果集中,字段需要一致。

  • union
    该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。
    案例:查询id小于3,或者名字为“英文”的课程:
select * from course where id<3
union
select * from course where name='英文';
-- 或者使用or来实现
select * from course where id<3 or name='英文';

注意点:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值