SQL执行顺序

  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;

### SQL 查询执行顺序解析 SQL 查询的执行顺序并不完全按照书写的顺序,而是有一个特定的逻辑顺序。以下是详细的解析: #### 实际执行顺序 1. **FROM**: 首先处理 FROM 子句,确定查询的数据源表或视图[^1]。如果涉及多个表,则会在此阶段完成笛卡尔积计算。 2. **ON**: 如果存在 JOIN 条件,在此阶段应用 ON 的条件过滤数据集[^2]。 3. **OUTER JOIN**: 处理外连接操作,保留未匹配的行[^3]。 4. **WHERE**: 应用 WHERE 过滤条件,进一步缩小结果集范围。 5. **GROUP BY**: 对满足 WHERE 条件的结果进行分组操作[^2]。 6. **HAVING**: 在 GROUP BY 后筛选符合条件的分组[^1]。 7. **SELECT**: 执行 SELECT 列表的选择操作,决定最终要显示哪些字段[^4]。 8. **DISTINCT**: 去重操作发生在 SELECT 之后,确保结果集中没有重复记录[^3]。 9. **ORDER BY**: 根据指定的列对结果集进行排序[^4]。 10. **LIMIT/OFFSET**: 最后一步是对结果集进行截取或偏移操作,控制返回的行数。 #### 示例代码 以下是一个简单的 SQL 查询及其执行顺序的演示: ```sql SELECT DISTINCT column_name FROM table_name JOIN another_table ON table_name.id = another_table.foreign_id WHERE condition GROUP BY grouping_column HAVING group_condition ORDER BY sort_column ASC LIMIT row_count OFFSET offset_value; ``` 在这个例子中,实际执行顺序如下: 1. `FROM` 和 `JOIN`: 确定基础数据集合。 2. `ON`: 应用连接条件。 3. `WHERE`: 进一步过滤数据。 4. `GROUP BY`: 将数据分为若干组。 5. `HAVING`: 筛选符合条件的分组。 6. `SELECT`: 提取所需的列。 7. `DISTINCT`: 移除重复项。 8. `ORDER BY`: 排序结果。 9. `LIMIT/OFFSET`: 控制返回的行数和起始位置。 --- ### 数据库内部工作原理 除了外部可见的执行顺序之外,数据库系统还会经历更复杂的内部过程。例如,在 GaussDB 中,SQL 引擎负责解析、优化并生成执行计划,而存储引擎则具体执行这些计划[^3]。这种分工可以显著提高性能。 --- ### 性能注意事项 - 使用 `ORDER BY` 可能带来较大的开销,尤其是当需要对大量数据排序时[^4]。 - `LIMIT` 虽然位于最后,但在某些情况下可以通过提前裁剪减少中间结果集大小,提升效率。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值