准备工作
1、班级表
CREATE TABLE `t_learn_class` (
`id` varchar(30) NOT NULL COMMENT '班级id',
`name` varchar(30) NOT NULL COMMENT '班级名称',
`remark` varchar(100) NOT NULL COMMENT '备注',
`extend01` varchar(100) DEFAULT NULL COMMENT '扩展字段',
`extend02` varchar(100) DEFAULT NULL COMMENT '扩展字段',
`extend03` varchar(100) DEFAULT NULL COMMENT '扩展字段',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2、学生表
CREATE TABLE `t_learn_student` (
`id` varchar(30) NOT NULL COMMENT '学号',
`name` varchar(100) NOT NULL COMMENT '姓名',
`gender` varchar(4) NOT NULL DEFAULT '' COMMENT '性别',
`age` varchar(3) NOT NULL COMMENT '年龄',
`classid` varchar(30) NOT NULL COMMENT '班级id',
`extend01` varchar(100) DEFAULT NULL COMMENT '扩展字段',
`extend02` varchar(100) DEFAULT NULL COMMENT '扩展字段',
`extend03` varchar(100) DEFAULT NULL COMMENT '扩展字段',
UNIQUE KEY `pk_id` (`id`),
KEY `idx_classis` (`classid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3、成绩表
CREATE TABLE `t_learn_grade` (
`studentid` varchar(30) NOT NULL COMMENT '分数表',
`chinese` varchar(4) NOT NULL,
`math` varchar(4) NOT NULL,
`english` varchar(4) NOT NULL,
`extend1` varchar(100) DEFAULT NULL,
`extend2` varchar(100) DEFAULT NULL,
`extend3` varchar(100) DEFAULT NULL,
PRIMARY KEY (`studentid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
4、班级表数据
INSERT INTO `t_learn_class` VALUES ('001', '零零一', '学前班', NULL, NULL, NULL);
INSERT INTO `t_learn_class` VALUES ('101', '一零一', '一年级一班', NULL, NULL, NULL);
INSERT INTO `t_learn_class` VALUES ('102', '一零二', '一年级二班', NULL, NULL, NULL);
INSERT INTO `t_learn_class` VALUES ('401', '四零一', '四年级一班', NULL, NULL, NULL);
INSERT INTO `t_learn_class` VALUES ('402', '四零二', '四年级二班', NULL, NULL, NULL);
5、学生表数据
INSERT INTO `t_learn_student` VALUES ('1', '张三', '1', '18', '101', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('10', '李十二', '0', '23', '102', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('11', '万十三', '1', '52', '201', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('12', '王十四', '0', '23', '201', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('13', '屈十五', '1', '46', '201', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('14', '涂十六', '0', '52', '201', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('15', '程十七', '1', '23', '201', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('16', '赵十八', '0', '42', '202', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('17', '郑十九', '1', '34', '202', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('18', '程二十', '0', '25', '202', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('19', '涂二十一', '1', '42', '202', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('2', '李四', '0', '20', '101', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('20', '孙二十二', '0', '12', '202', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('3', '王五', '1', '10', '101', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('4', '赵六', '1', '18', '101', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('5', '徐七', '0', '14', '101', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('6', '陈八', '1', '13', '102', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('7', '许九', '1', '25', '102', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('8', '程十', '0', '42', '102', NULL, NULL, NULL);
INSERT INTO `t_learn_student` VALUES ('9', '张十一', '1', '14', '102', NULL, NULL, NULL);
6、成绩表数据
INSERT INTO `t_learn_grade` VALUES ('1', '80', '74', '69', NULL, NULL, NULL);
INSERT INTO `t_learn_grade` VALUES ('2', '79', '56', '88', NULL, NULL, NULL);
INSERT INTO `t_learn_grade` VALUES ('3', '99', '78', '87', NULL, NULL, NULL);
INSERT INTO `t_learn_grade` VALUES ('4', '67', '98', '67', NULL, NULL, NULL);
INSERT INTO `t_learn_grade` VALUES ('5', '98', '67', '100', NULL, NULL, NULL);
一、连接的使用
1、内连接——inner join
SELECT T1.ID,
T1.NAME,
T1.AGE,
T1.CLASSID,
T2.NAME
FROM T_LEARN_STUDENT T1
INNER JOIN T_LEARN_CLASS T2
ON T1.CLASSID = T2.ID;
查询结果:
2、左外连接——left join
SELECT T1.ID,
T1.NAME,
T1.AGE,
T1.CLASSID,
T2.NAME
FROM T_LEARN_STUDENT T1
LEFT JOIN T_LEARN_CLASS T2
ON T1.CLASSID = T2.ID;
查询结果:
3、右外连接——right join
SELECT T1.ID,
T1.NAME,
T1.AGE,
T1.CLASSID,
T2.NAME
FROM T_LEARN_STUDENT T1
RIGHT JOIN T_LEARN_CLASS T2
ON T1.CLASSID = T2.ID;
查询结果:
4、全外连接——full join
SELECT T1.ID,
T1.NAME,
T1.AGE,
T1.CLASSID,
T2.NAME
FROM T_LEARN_STUDENT T1
FULL JOIN T_LEARN_CLASS T2
ON T1.CLASSID = T2.ID;
查询报错,mysql不支持全外连接,使用UNIOIN方式实现全外连接
SELECT T1.ID,
T1.NAME,
T1.AGE,
T1.CLASSID,
T2.NAME
FROM T_LEARN_STUDENT T1
LEFT JOIN T_LEARN_CLASS T2
ON T1.CLASSID = T2.ID
UNION
SELECT T1.ID,
T1.NAME,
T1.AGE,
T1.CLASSID,
T2.NAME
FROM T_LEARN_STUDENT T1
RIGHT JOIN T_LEARN_CLASS T2
ON T1.CLASSID = T2.ID
查询结果:
5、交叉连接——cross join
SELECT T1.ID,
T1.NAME,
T1.AGE,
T1.CLASSID,
T2.NAME
FROM T_LEARN_STUDENT T1
CROSS JOIN T_LEARN_CLASS T2
查询结果,部分数据:
二、行列转换
1、行转换列
统计每个班的人数
SELECT count(*),
T1.classid
FROM T_LEARN_STUDENT T1
group by T1.classid
查询结果:
使用cross join方式
SELECT *
FROM ( SELECT COUNT(*) '101'
FROM T_LEARN_STUDENT T1
WHERE CLASSID = '101'
) TT1
CROSS JOIN
( SELECT COUNT(*) '102'
FROM T_LEARN_STUDENT T2
WHERE CLASSID = '102'
) TT2
CROSS JOIN
( SELECT COUNT(*) '201'
FROM T_LEARN_STUDENT T3
WHERE CLASSID = '201'
) TT3
CROSS JOIN
( SELECT COUNT(*) '202'
FROM T_LEARN_STUDENT T4
WHERE CLASSID = '202'
) TT4
转换后的结果:
使用case when方式
SELECT count(case when classid = '101' then id end) '101',
count(case when classid = '102' then id end) '102',
count(case when classid = '201' then id end) '201',
count(case when classid = '202' then id end) '202'
FROM T_LEARN_STUDENT
转换结果:
2、列转换行
将成绩表的列形式数据转换成行数据
表数据如下:
使用union all方式
select studentid, 'chinese' subject, chinese 'grade' from t_learn_grade
union all
select studentid, 'math' subject, math 'grade' from t_learn_grade
union all
select studentid, 'english' subject, english 'grade' from t_learn_grade
转换后结果如下:
3、explain解读
查询101班的学生成绩表
select t1.name '班级名',
t2.name '姓名',
t3.chinese '语文',
t3.math '数学',
t3.english '英语'
from t_learn_class t1
left join t_learn_student t2 on t1.id = t2.classid
left join t_learn_grade t3 on t3.studentid = t2.id
where t2.classid = '101';
执行计划的使用:
explain
select t1.name '班级名',
t2.name '姓名',
t3.chinese '语文',
t3.math '数学',
t3.english '英语'
from t_learn_class t1
left join t_learn_student t2 on t1.id = t2.classid
left join t_learn_grade t3 on t3.studentid = t2.id
where t2.classid = '101';
执行计划如下:
select_type:三个表都是simple,是简单查询
table:分别对应是t1,t2,t3表
partitions:三张表都未使用分区
type:对t1表是const常量级别,对t2表是连接查询, 对t3表是更优的查询
possible_keys:可能使用的索引
key:实际使用的索引,t1,t3使用的是主键,t2使用的是索引
key_len:索引长度
ref:连接的级别,t1,t2是常量级别连接
rows:行数
filtered:100%
Extra:备注信息,t2表使用了索引
引擎简介
实际开发会用到的三种引擎:InnoDB,MyIsAM,MEMORY
InnoDB:使用最多的引擎,存储限制64TB(够用)。支持事务管理,在SpringBoot使用事务注解,操作的表必须是这种引擎,否则事务会失效。对表数据进行操作时,锁的是行数据,即其他的行数据,不会被锁。
MyIsAm:较常用的引擎,存储限制256TB。不支持事务管理,事务注解会失效。对表数据进行操作时,锁的是全表。
MEMORY:常用于临时表,表数据存储在内存中,数据会丢失。
分区表
工作中常常会创建日志分区表来存储日志,下面创建一个日志分区表
CREATE TABLE `t_learn_log` (
`logid` varchar(30) NOT NULL COMMENT '日志id',
`platform` varchar(30) NOT NULL COMMENT '对端',
`url` varchar(500) NOT NULL COMMENT '请求url',
`reqbody` text COMMENT '请求报文',
`respbody` text COMMENT '返回报文',
`createtime` datetime NOT NULL COMMENT '创建时间',
`costtime` varchar(10) NOT NULL COMMENT '耗时',
`result` varchar(4) NOT NULL COMMENT '结果:0为成功,1为是失败',
`extend01` varchar(255) DEFAULT NULL COMMENT '扩展字段一',
`extend02` varchar(255) DEFAULT NULL COMMENT '扩展字段二',
`extend03` varchar(255) DEFAULT NULL COMMENT '扩展字段三',
PRIMARY KEY (`logid`,`createtime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
PARTITION BY RANGE COLUMNS(createtime)
(PARTITION p202009 VALUES LESS THAN ('2020-10-01') ENGINE = InnoDB,
PARTITION p202010 VALUES LESS THAN ('2020-11-01') ENGINE = InnoDB,
PARTITION p202011 VALUES LESS THAN ('2020-12-01') ENGINE = InnoDB,
PARTITION p202012 VALUES LESS THAN ('2021-01-01') ENGINE = InnoDB,
PARTITION p202101 VALUES LESS THAN ('2021-02-01') ENGINE = InnoDB,
PARTITION p202102 VALUES LESS THAN ('2021-03-01') ENGINE = InnoDB,
PARTITION p202103 VALUES LESS THAN ('2021-04-01') ENGINE = InnoDB,
PARTITION p202104 VALUES LESS THAN ('2021-05-01') ENGINE = InnoDB,
PARTITION p202105 VALUES LESS THAN ('2021-06-01') ENGINE = InnoDB,
PARTITION p202106 VALUES LESS THAN ('2021-07-01') ENGINE = InnoDB,
PARTITION p202107 VALUES LESS THAN ('2021-08-01') ENGINE = InnoDB,
PARTITION p202108 VALUES LESS THAN ('2021-09-01') ENGINE = InnoDB,
PARTITION p202109 VALUES LESS THAN ('2021-10-01') ENGINE = InnoDB,
PARTITION p202110 VALUES LESS THAN (MAXVALUE) ENGINE = InnoDB);
分区表的分区字段必须是主键的一部分,可以是联合主键。