目录
一、表的设计
三大范式:
1.1 一对一
1.2 一对多
1.3 多对多
1.4设计表与插入数据
- 创建班级表
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),
email 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,
foreign key (student_id) references student (id),
foreign key (course_id) references course (id)
);
- 对班级表插入数据
insert into classes(name, `desc`) values
('计算机系2019级1班', '学习了计算机原理、C和Java语言、数据结构和算法'),
('中文系2019级3班','学习了中国传统文学'),
('自动化2019级5班','学习了机械自动化');
- 学生表插入数据
insert into student(sn, name, email, classes_id) values
('09982','黑旋风李逵','[email protected]',1),
('00835','菩提老祖',null,1),
('00391','白素贞',null,1),
('00031','许仙','[email protected]',1),
('00054','不想毕业',null,1),
('51234','好好说话','[email protected]',2),
('83223','tellme',null,2),
('09527','老外学中文','[email protected]',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.5表中数据拷贝
语法:
insert into table_name(列名1,列名2) select ....
案例:创建一张用户表,设计有name姓名、email邮箱、sex性别、mobile手机号字段。需要把已有的学生数据复制进来,可以复制的字段为name、qq_mail
create table test_user (
id int primary key auto_increment,
name varchar(20) comment '姓名',
age int comment '年龄',
email varchar(20) comment '邮箱',
sex varchar(1) comment '性别',
mobile varchar(20) comment '手机号'
);-- 将学生表中的所有数据复制到用户表
insert into test_user(name, email) select name, qq_mail from student;
二、复杂查询
前面介绍过数据库的基本查询也就是单表数据查询,这里要介绍的是数据库中的多表查询
2.1 聚合查询
2.1.1聚合函数
常见的统计总数、计算平局值等操作,可以使用聚合函数来实现,常见的聚合函数有:
函数 | 说明 |
count([distinct] expr) | 返回查询到的数据的 数量 |
sum([distinct] expr) | 返回查询到的数据的 总和,不是数字没有意义 |
avg([distinct] expr) | 返回查询到的数据的 平均值,不是数字没有意义 |
max([distinct] expr) | 返回查询到的数据的 最大值,不是数字没有意义 |
min([distinct] expr) | 返回查询到的数据的 最小值,不是数字没有意义 |
案例:
- count 对数据行进行统计
--统计班级共有多少同学
select count(*) from student; --统计有多少行数据
select count(0) from student; --统计主键列有多少行数据
-- 统计班级收集的 email 有多少个,email 为 null的数据不会计入结果
select count(email) from student;
通过这个统计我们发现当数据为空的时候是不会进行统计的
- sum 计算数据列的数据总和(只能针对数字)
-- 统计数学成绩总分
select sum(math) from exam_result;
-- 不及格 < 60 的总分,没有结果,返回 NULL
select sum(math) from exam_result where math < 60;
- avg 对数据列的数据进行求平均(只针对数字)
-- 统计平均总分
select avg(english + chinese + math) from exam_result ;
- max 针对某列数据取最大值(只针对数字)
-- 返回英语最高分
select max(english) from exam_result;
- min针对某列数据取最小值(只针对数字)
-- 返回 > 70 分以上的数学最低分
select min(math) from exam_result where math > 70;
2.1.2 group by子句
select 中使用 group by 子句可以对指定列进行分组查询。需要满足:使用 group by 进行分组查询时,select指定的字段必须是“分组依据字段”,其他字段若想出现在select中则必须包含在聚合函数中。
案例:准备测试表:职员表,有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);
--查询每个角色的最高工资、最低工资和平均工资
select role,max(salary),min(salary),avg(salary)
from emp group by role;
2.1.3 having
group by 子句进行分组以后,需要对分组结果再进行条件过滤时,不能使用 where 语句,而需要用 having。但是一个语句中也可以同时含有where与having
--显示平均工资低于1500的角色和它的平均工资
select role,avg(salary) from emp group by role
having avg(salary) < 1500;
--显示除掉董事长并且平均工资高于1500的角色与平均工资
select role, avg(salary) from emp where role !='董事长'
group by role having avg(salary) > 1500;