1、 SQL的执行顺序对于了解高级SQL是个很必要的知识。了解SQL的执行顺序,对于分析高级SQL还是很有必要的,先明确处理的过程阶段,然后查看每个阶段里的SQL怎么写的,这个阶段是如何处理,产生了什么,有什么作用等,以点化面,慢慢扩散知识体系。测试SQL在MYSQL8.0版本环境。
/*
以下边SQL查简单的查询作为例子解析,SQL处理的大致阶段可以分为:
1、from:表的预处理。
这一步若是存在表连结(表连结指的是自联结,自然连接,外连接,我们一般常用的是外连接left join,right join ,full join 等,
如例子中的就是左外连结)的操作的话,
第一步都是生成笛卡尔积(表1行*表2行)虚拟表,若是存在多个表连结,按顺序连接表1表2,表1和表2生成的虚拟表TA1再连接剩下的
表3生成虚拟表TA2(依次类推),然后根据ON筛选器的条件,从连接表的虚拟表TA2中返回符合条件的行,得到FROM阶段的表预处理虚拟表TA3。
2、where:根据where后的条件,从TA3中返回符合条件的行,作为虚拟表TB1
3、groupby:依据分组的列(select部分所有字段,使用聚合函数处理的字段除外,如下例子中,我的groupby条件就应该是t.cname,t.credit),
从TB1中返回分组后的数据,生成虚拟表TC1
4、having:依据条件对虚拟表TC1分组后的数据进行筛选,生成虚拟表TD1
5、select: 投影查询所需字段,从TD1中返回,生成虚拟表TE1,存在DISTINCT,则去重生成虚拟表TF1
6、order by:根据排序选择字段对TF1进行排序,生成游标TG1(此步骤可以使用列的别名,排序后,生成的是数据库对象)
7、limit:若是存在LIMIT的话,根据limit条件返回虚拟表TH1,返回结果。
*/
SELECT distinct -- 5、select 操作部分
t.cname,
t.credit,
sum(t.semester)num
FROM
course t
LEFT JOIN course_history a ON a.cno = t.cno -- 1、from表连结部分,最终预处理虚拟表TA3
where t.credit>=3 -- 2、where条件处理部分,虚拟表TB1
group by t.cname,t.credit -- 3、分组部分,虚拟表TC1
having t.credit!=3 -- 4、分组后条件筛选,虚拟表TD1
order by t.cname -- 6、排序部分,游标TG1
limit 2 -- 7、limit限制返回行数,虚拟表TH1
2、测试数据表(创建插入数据)
/*
Navicat Premium Data Transfer
Source Server : mysql8.0
Source Server Type : MySQL
Source Server Version : 80028
Source Host : localhost:3306
Source Schema : 测试库2
Target Server Type : MySQL
Target Server Version : 80028
File Encoding : 65001
Date: 28/05/2022 12:55:51
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for course
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
`cno` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '课程号',
`cname` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '课程名',
`credit` int(0) NULL DEFAULT NULL COMMENT '学分',
`semester` int(0) NULL DEFAULT NULL COMMENT '开课学期',
PRIMARY KEY (`cno`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of course
-- ----------------------------
INSERT INTO `course` VALUES ('C001', '高等数学', 4, 1);
INSERT INTO `course` VALUES ('C002', '大学英语', 3, 1);
INSERT INTO `course` VALUES ('C003', '大学英语', 3, 2);
INSERT INTO `course` VALUES ('C004', '计算机文化学', 2, 2);
INSERT INTO `course` VALUES ('C005', 'Java', 2, 3);
INSERT INTO `course` VALUES ('C006', '数据库基础', 4, 5);
INSERT INTO `course` VALUES ('C007', '数据结构', 4, 4);
INSERT INTO `course` VALUES ('C008', '计算机网络', 4, 4);
-- ----------------------------
-- Table structure for course_history
-- ----------------------------
DROP TABLE IF EXISTS `course_history`;
CREATE TABLE `course_history` (
`cno` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '课程号',
`cname` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '课程名',
`credit` int(0) NULL DEFAULT NULL COMMENT '学分',
`semester` int(0) NULL DEFAULT NULL COMMENT '开课学期',
PRIMARY KEY (`cno`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of course_history
-- ----------------------------
INSERT INTO `course_history` VALUES ('C001', '高等数学', 4, 1);
INSERT INTO `course_history` VALUES ('C002', '大学英语', 3, 1);
INSERT INTO `course_history` VALUES ('C003', '大学英语', 3, 2);
INSERT INTO `course_history` VALUES ('C004', '计算机文化学', 2, 2);
INSERT INTO `course_history` VALUES ('C005', 'Java', 2, 3);
INSERT INTO `course_history` VALUES ('C006', '数据库基础', 4, 5);
INSERT INTO `course_history` VALUES ('C007', '数据结构', 4, 4);
INSERT INTO `course_history` VALUES ('C008', '计算机网络', 4, 4);
INSERT INTO `course_history` VALUES ('C009', '移动通信', 3, 3);
INSERT INTO `course_history` VALUES ('C010', '中国文学近代史', 5, 4);
SET FOREIGN_KEY_CHECKS = 1;