12. SQL -- 查询解析步骤

先从最简单的 SQL 入手来分析一下 SQL 的执行步骤,为什么了解执行步骤,其实与 JOIN 后的 ON 条件和 WHERE 条件容易混淆有关系。

是先执行 ON 还是先执行 WHERE ,很大程度上会决定 SQL 的结果集正确与否。

CREATE TABLE Customers

(

CustomerID  CHAR(5)     NOT NULL PRIMARY KEY,

City        VARCHAR(10) NOT NULL

);

CREATE TABLE Orders

(

OrderID     INT     NOT NULL PRIMARY KEY,

CustomerID  CHAR(5) NULL REFERENCES Customers(CustomerID)

);

INSERT INTO Customers VALUES(‘FISSA‘,‘Madrid‘);

INSERT INTO Customers VALUES(‘FRNDO‘,‘Madrid‘);

INSERT INTO Customers VALUES(‘KRLOS‘,‘Madrid‘);

INSERT INTO Customers VALUES(‘MRPHS‘,‘Zion‘);

INSERT INTO Orders VALUES(1,‘FRNDO‘);

INSERT INTO Orders VALUES(2,‘FRNDO‘);

INSERT INTO Orders VALUES(3,‘KRLOS‘);

INSERT INTO Orders VALUES(4,‘KRLOS‘);

INSERT INTO Orders VALUES(5,‘KRLOS‘);

INSERT INTO Orders VALUES(6,‘MRPHS‘);

INSERT INTO Orders VALUES(7,NULL);

试看看以上两个语句有什么不同,你就会发现很有趣的现象。

SELECT C.CustomerID,COUNT(O.OrderID) AS NumOrders

FROM Customers C

LEFT OUTER JOIN Orders O

ON C.CustomerID=O.CustomerID

WHERE C.City=‘Madrid‘

GROUP BY C.CustomerID

HAVING COUNT(O.OrderID)<3

ORDER BY NumOrders;

SELECT C.CustomerID,COUNT(O.OrderID) AS NumOrders

FROM Customers C

LEFT OUTER JOIN Orders O

ON C.CustomerID=O.CustomerID

AND C.City=‘Madrid‘

GROUP BY C.CustomerID

HAVING COUNT(O.OrderID)<3

ORDER BY NumOrders;

--Step1 ,首先对 FROM 后面的表进行笛卡尔乘积,生成虚表 STEP1

WITH STEP1

AS

(

SELECT C.CustomerID C_CustomerID,C.City C_City,O.OrderID O_OrderID,O.CustomerID O_CustomerID

FROM Customers C,Orders O

)

SELECT * FROM STEP1

--Step2 ,再次应用 ON 语句中的条件,如果没有外关联的话,这里的 ON 和 WHERE 实际上是没有什么差别的,生成虚表 STEP2

WITH STEP2

AS

(

SELECT C.CustomerID C_CustomerID,C.City C_City,O.OrderID O_OrderID,O.CustomerID O_CustomerID

FROM Customers C

JOIN Orders O

ON C.CustomerID=O.CustomerID

)

SELECT * FROM STEP2

--Step3 ,如果指定了 OUTER JOIN , SQL 会自动把 STEP2 表中未匹配的行作为外部行添加到 STEP3 中,此处找到了 CustomerID=FISSA,City=Madrid ,这个没有订单但又有相关名字的用户

WITH STEP3

AS

(

SELECT C.CustomerID C_CustomerID,C.City C_City,O.OrderID O_OrderID,O.CustomerID O_CustomerID

FROM Customers C

LEFT OUTER JOIN Orders O

ON C.CustomerID=O.CustomerID

)

SELECT * FROM STEP3

--Step4 ,应用 WHERE 条件,过滤不符合条件的记录

AS

(

SELECT C.CustomerID C_CustomerID,C.City C_City,O.OrderID O_OrderID,O.CustomerID O_CustomerID

FROM Customers C

LEFT OUTER JOIN Orders O

ON C.CustomerID=O.CustomerID

WHERE C.City=‘Madrid‘

)

SELECT * FROM STEP4

--Step5 ,对以上的结果集进行分组

WITH STEP5

AS

(

SELECT C.CustomerID,COUNT(O.OrderID) AS NumOrders

FROM Customers C

LEFT OUTER JOIN Orders O

ON C.CustomerID=O.CustomerID

WHERE C.City=‘Madrid‘

GROUP BY C.CustomerID

)

SELECT * FROM STEP5

--Step6 ,处理 CUBE 、 ROLLUP 之类的语句,此处无此需求

SELECT * FROM STEP6

--Step7 处理 Having 筛选器,与 WHERE 条件有些类似

WITH STEP7

AS

(

SELECT C.CustomerID,COUNT(O.OrderID) AS NumOrders

FROM Customers C

LEFT OUTER JOIN Orders O

ON C.CustomerID=O.CustomerID

WHERE C.City=‘Madrid‘

GROUP BY C.CustomerID

HAVING COUNT(O.OrderID)<3

)

SELECT * FROM STEP7

--Step8 ,处理 SELECT 列表,即别名转换把 COUNT(O.OrderID) 转换成 NumOrders

SELECT * FROM STEP8

--Step9 ,应用 DISTINCT 语句,此处无此需求

SELECT * FROM STEP9

--Step10 ,应用 ORDER BY 语句进行排序

SELECT C.CustomerID,COUNT(O.OrderID) AS NumOrders

FROM Customers C

LEFT OUTER JOIN Orders O

ON C.CustomerID=O.CustomerID

WHERE C.City=‘Madrid‘

GROUP BY C.CustomerID

HAVING COUNT(O.OrderID)<3

ORDER BY NumOrders

--Step11 ,执行 TOP 选项,此处无此需求

SELECT * FROM STEP11

时间: 2024-12-10 04:01:50

12. SQL -- 查询解析步骤的相关文章

kotlin 写的一个简单 sql 查询解析器

1 package com.dx.efuwu.core 2 3 import org.apache.commons.lang.StringUtils 4 import java.sql.PreparedStatement 5 6 /** 7 * sql 模板处理 8 * @author sunzq 9 * 2017/06/02 10 */ 11 12 /** 13 * 查询的一个条件句 14 */ 15 class QueryBranch(val content: String, val key

SQL查询多条不重复记录值简要解析【转载】

转载http://hi.baidu.com/my_favourate/item/3716b0cbe125f312505058eb SQL查询多条不重复记录值简要解析2008-02-28 11:36 以下内容在Oracle 10g下测试由于设计需要,需要查询不重复的记录值,同类问题,想必大家都遇到过,于是乎马上GOOGLE一下,发现此类问题还挺多,解决方案也不少,仔细看看.例如有如下表结构和值tablefid   name sex1     a      男2     b      男3    

sql查询语句如何解析成分页查询?

我们公司主要mysql存储数据,因此也封装了比较好用mysql通用方法,然后,我们做大量接口,在处理分页查询接口,没有很好分查询方法.sql查询 语句如何解析成“分页查询”和“总统计”两条语句.可能,很多人在处理“总统计”是这样:“select count(*) from (<sql原查询语句>) ”,而不是把原sql查询语句中columns替换成“count(*)”:相比前者统计查询效率高不高,大家心知肚明.“分页查询”很简单,对于mysql语句就是在原sql查询语句后面加上“limit 数

【T-SQL进阶】02.理解SQL查询的底层原理

本系列[T-SQL]主要是针对T-SQL的总结. T-SQL基础 [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础]02.联接查询 [T-SQL基础]03.子查询 [T-SQL基础]04.表表达式-上篇 [T-SQL基础]04.表表达式-下篇 [T-SQL基础]05.集合运算 [T-SQL基础]06.透视.逆透视.分组集 [T-SQL基础]07.数据修改 [T-SQL基础]08.事务和并发 [T-SQL基础]09.可编程对象 T-SQL进阶 [T-SQL进阶]01.好用的SQ

Report Studio值提示通过prompt宏函数给sql查询传参

场景:当我们在DW中新建了一个表,但是在FM中没有创建模型,想针对这个表直接做一个报表,那么就需要在reportstudio中直接用sql来查询,为了追求查询速度,我们可以把页面用户选择的条件直接传给sql. 如下图:上面是省份对应key值为1-2-3-4-5,下面是商品类型对应key值为1-2,省份选择1,5类型选择1则出现想要的数据 实现步骤: 1:从工具箱拖一个sql,每个sql会绑定一个查询接收sql的查询结果,如下图 2:指定sql引用的数据源,数据源已经在CognosConnecti

MySQL技术探索01实现SQL语法解析器

本文将介绍如何使用开源的语法和词法分析框架bison和flex来实现SQL解析器.出于技术学习的目的,本文做描述的微型SQL解析器仅能实现对微型SQL的语法解析. 1.MySQL中的SQL解析器 包括JDBC.ODBC.ADO等等关系数据库客户端应用开发框架在内的各种SDK,核心功能是帮助程序员简化各种客户端的数据库操作,同时将SQL语句通过网络形式发送给MySQL等关系数据库的服务器进程.MySQL服务器进行负责解析并执行这些SQL语句.SQL语句中的语法规则多种多样,MySQL服务器是如何实

理解SQL查询的底层原理

阅读目录 一.SQL Server组成部分 二.查询的底层原理 本系列[T-SQL]主要是针对T-SQL的总结. T-SQL基础 [T-SQL基础]01.单表查询-几道sql查询题 [T-SQL基础]02.联接查询 [T-SQL基础]03.子查询 [T-SQL基础]04.表表达式-上篇 [T-SQL基础]04.表表达式-下篇 [T-SQL基础]05.集合运算 [T-SQL基础]06.透视.逆透视.分组集 [T-SQL基础]07.数据修改 [T-SQL基础]08.事务和并发 [T-SQL基础]09

提高SQL查询效率

1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from t where num=0 3.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放

Sql Server 优化 SQL 查询:如何写出高性能SQL语句

1. 首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用 “全表扫描”方式. 可见,执行计划并不是固定的,它是“个性化的”.产生一个正确的“执行计划”有两点很重要: (1)    SQL语句是否清晰地告诉查询优化器它想干什么? (2)