标签:SQL SERVER/MSSQL SERVER/数据库/DBA/查询步骤

概述

查询步骤是很基础也挺重要的一部分,但是我还是在周围发现有些人虽然会语法,但是对于其中的步骤不是很清楚,这里就来分解一下其中的步骤,在技术内幕系列里面都会有讲到。

目录

流程图

 (1)FROM <LEFT_TABLE> <JOIN_TYPE> JOIN <RIGHT_TABLE> ON <ON_PREDICATE>
|<LEFT_TABLE> <APPLY_TYPE> APPLY <RIGHT_TABLE_EXPRESSION> AS <alias>
|<LEFT_TABLE> pivot(<pivot_specification>) AS <alias>
|<LEFT_TABLE> UNPIVOT(<unpivot_specification>) AS <alias>
(2)WHERE<where_predicate>
(3)GROUP BY<group_by_specification>
(4)HAVING<having_predicate>
(5)SELECT <DISTINCT> <TOP> <select_list>
(6)ORDER BY<order_by_list>

步骤分解

测试数据

--创建测试表

--创建顾客表
CREATE TABLE Customers
(custid INT NOT NULL PRIMARY KEY,
city NVARCHAR(20) NOT NULL
)
go
INSERT INTO Customers VALUES(1,'深圳'),(2,'广州'),(3,'武汉'),(4,'上海'),(5,'北京') --创建订单表
CREATE TABLE Orders
(orderid INT NOT NULL PRIMARY KEY IDENTITY(1000,1),
custid INT NOT NULL,
orderdate DATETIME NOT NULL
)
GO
INSERT INTO Orders(custid,orderdate)values(1,'2013-10-1 00:00:00'),(1,'2013-10-2 00:00:00'),(1,'2013-10-3 00:00:00'),(1,'2013-10-4 00:00:00'),(2,'2013-10-1 00:00:00'),(2,'2013-10-3 00:00:00'),(2,'2013-10-5 00:00:00'),(3,'2013-10-3 00:00:00'),(3,'2013-10-7 00:00:00'),(4,'2013-10-1 00:00:00') --创建订单明细表
CREATE TABLE [OrderDetails](
[orderid] [int] NOT NULL,
[productid] [int] NOT NULL,
[unitprice] [money] NOT NULL,
[qty] [smallint] NOT NULL
CONSTRAINT [PK_OrderDetails] PRIMARY KEY CLUSTERED
(
[orderid] ASC,
[productid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
INSERT INTO OrderDetails VALUES(1000,10,5.00,1),(1000,14,6.00,2),(1001,10,5.31,3),(1001,11,5.22,1),(1001,12,3.20,3),(1001,13,4.10,2),(1002,11,7.00,1),(1003,12,8.00,5),(1004,13,8.41,1),(1004,11,6.65,1),(1005,18,7.41,1),(1006,17,10.00,1)
--查询深圳、广州每一个顾客每笔金额大于10的订单,并按订单价格倒序排序
SELECT TA.custid,TB.orderid,SUM(tc.unitprice*tc.qty) AS price FROM Customers TA LEFT JOIN Orders TB ON TA.custid=TB.custid LEFT JOIN OrderDetails TC ON TB.orderid=tc.orderid
WHERE TA.city IN('深圳','广州')
GROUP BY TA.custid,TB.orderid
HAVING SUM(tc.unitprice*tc.qty)>10
ORDER BY price DESC

第一步:FROM阶段

这一步是一个T-SQL语句的开始,一般紧接着FROM的这个表被称作左表,例如a inner join b inner join c,首先a作为左表然后关联b,a和b关联的结果作为下一个运算的左表关联c。在FROM阶段涉及的表运算会有JOIN(LEFT JOIN,RIGHT JOIN,FULL JOIN),APPLY(CROSS APPLY,OUTER APPLY),PIVOT,UNPIVOT

对于上面的查询例子:FROM Customers TA LEFT JOIN Orders TB ON TA.custid=TB.custid的左连接的分解是这样的

第一步交叉连接、SELECT * FROM Customers TA CROSS JOIN Orders TB---首先进行交叉连接得到的行数是5*10=50行

第二步ON筛选、将TA.custid=TB.custid以外的结果排除,可以等价于SELECT * FROM Customers TA CROSS JOIN Orders TB WHERE TA.custid=TB.custid
第三步、将主表(左边的表)不在第二步的行加上,可以等价于 SELECT * FROM Customers TA CROSS JOIN Orders TB WHERE TA.custid=TB.custid union all SELECT * FROM Customers TA LEFT JOIN Orders TB ON TA.custid=TB.custid WHERE TB.custid IS NULL

所以其它几个表运算只要大家知道怎么使用就可以了,大家只要明白它在T-SQL语句中的位置就行。

这里要注意一点:大家理解了JEFT JOIN的原理之后就明白"on"筛选对查询的删除不是最终的,在上面的第三步会把主表的一些行又添加上来,所以我们有时候写LEFT JOIN的时候有的人不太明白为什么ON 后面加AND和把AND放在WHERE里面的得到的结果不一样,就是这个原理了,WHERE操作对查询的删除才是最终的。

第二步:WHERE阶段

当然后面的有些阶段都是可选的也就是有的查询不一定会用到,但是这里为了讲述整个过程,所以就一步一步的来讲,在FROM 阶段结束之后会生成一张虚拟表,进入第二阶段也就是WHERE阶段,在WHERE阶段是对前一阶段(FROM阶段)结果返回行进行筛选,例如上面的查询筛选城市是‘深圳’,‘广州’的顾客

所以为什么把select步骤里面生成的列写在where里面无法识别就是因为where在select操作之前。

第三步:GROUP BY阶段

GROUP BY 操作是分组操作,确保进行分组的属性集每一个组都是唯一的,GROUP BY 操作的数据是WHERE阶段筛选之后的数据,例如上面的查询例子是将custid,orderid作为一行来进行分组,上面的例子是每一个顾客每一笔订单的消费金额。

第四步:HAVING阶段

HAVING阶段是在GOUP BY 阶段返回TURE之后才会有这步操作,HAVING是对上一步的分组之后的数据进行筛选的步骤,例如筛选消费订单金额大于10的顾客订单

第五步:SELECT阶段

select阶段是返回上一步操作得到的虚拟表的数据列,所以也就是为什么存在group by的分组查询,select里面的列跟group by 的分组列需要一致的原因了,聚会函数生成的列除外,因为select查询的基础列就是来源于前面的步骤,select阶段会涉及到去重复distinct当然如果前面存在分组也就不存在重复了,TOP操作,还有一些字段之间的算法运算,子查询等等。

第六步:ORDER BY阶段

这一步是整个过程的最后一步操作,因为它在SELECT阶段之后,所以对于SELECT里面生成的字段别名在ORDER BY 中可以使用别名,对于一张表,表代表的是集合,集合是没有顺序的,当一个查询带有ORDER BY时我们可以把它理解成游标,游标是有特定的排序,所以为什么一个查询加上ORDER BY 操作之后会变的很慢了,因为它需要进行排序操作。

---当查询没有排序时
SELECT * FROM Orders

---当查询有排序时
SELECT * FROM Orders
ORDER BY CUSTID

TOP于ORDER BY的关系

order by 是保证结果排序顺序,top是一个逻辑运算操作

对于一个没有外部查询的语句,order by 操作既能保证结果根据制定条件的排序,又能满足TOP的逻辑运算(查询最小的三个orderid)
SELECT TOP (3) * FROM Orders
ORDER BY ORDERID
对于存在外部查询时,order by在作用仅仅是保证top的逻辑结果的正确输出,而不能保证查询结果的排序,虽然我们可能查询出的结果是按照这个方式排序。
---当不指定TOP时报错
SELECT * FROM(SELECT custid,orderid,orderdate FROM Orders ORDER BY orderdate DESC) AS A
---当指定
SELECT * FROM(SELECT TOP (3) custid,orderid,orderdate FROM Orders ORDER BY orderdate DESC) AS A

总结

理解完了整个查询的过程,也就能能理解为什么SQLServer这么耗内存了,每一步的操作都是生成一张虚拟表进入下一步操作,理解了整个查询过程 之后对我们理解T-SQL语法很有帮助,同时也有利于分析语句。

如果文章对大家有帮助,希望大家能给个赞,谢谢!!!

备注:

作者:pursuer.chen

博客:http://www.cnblogs.com/chenmh

本站点所有随笔都是原创,欢迎大家转载;但转载时必须注明文章来源,且在文章开头明显处给明链接,否则保留追究责任的权利。

《欢迎交流讨论》

SQL Server 查询分解的更多相关文章

  1. [转] 利用SET STATISTICS IO和SET STATISTICS TIME 优化SQL Server查询性能

    首先需要说明的是这篇文章的内容并不是如何调节SQL Server查询性能的(有关这方面的内容能写一本书),而是如何在SQL Server查询性能的调节中利用SET STATISTICS IO和SET ...

  2. SQL SERVER 查询性能优化——分析事务与锁(五)

    SQL SERVER 查询性能优化——分析事务与锁(一) SQL SERVER 查询性能优化——分析事务与锁(二) SQL SERVER 查询性能优化——分析事务与锁(三) 上接SQL SERVER ...

  3. SQL Server 查询性能优化 相关文章

    来自: SQL Server 查询性能优化——堆表.碎片与索引(一) SQL Server 查询性能优化——堆表.碎片与索引(二) SQL Server 查询性能优化——覆盖索引(一) SQL Ser ...

  4. 利用SET STATISTICS IO和SET STATISTICS TIME 优化SQL Server查询性能

    首先需要说明的是这篇文章的内容并不是如何调节SQL Server查询性能的(有关这方面的内容能写一本书),而是如何在SQL Server查询性能的调节中利用SET STATISTICS IO和SET ...

  5. 如何找出你性能最差的SQL Server查询

    我经常会被反复问到这样的问题:”我有一个性能很差的SQL Server.我如何找出最差性能的查询?“.因此在今天的文章里会给你一些让你很容易找到问题答案的信息向导. 问SQL Server! SQL ...

  6. 使用WinDbg调试SQL Server查询

    上一篇文章我给你介绍了WinDbg的入门,还有你如何能附加到SQL Server.今天的文章,我们继续往前一步,我会向你展示使用WinDbg调试SQL Server查询需要的步骤.听起来很有意思?我们 ...

  7. sql server 查询分析器消息栏里去掉“(5 行受影响)”

    sql server 查询分析器消息栏里去掉"(5 行受影响)"     在你代码的开始部分加上这个命令: set nocount on   记住在代码结尾的地方再加上: set ...

  8. Sql Server查询性能优化之走出索引的误区

    据了解绝大多数开发人员对于索引的理解都是一知半解,局限于大多数日常工作没有机会.也什么没有必要去关心.了解索引,实在哪天某个查询太慢了找到查询条件建个索引就ok,哪天又有个查询慢了,再建立个索引就是, ...

  9. SQL Server 查询分析器提供的所有键盘快捷方式(转)

    下表列出 SQL Server 查询分析器提供的所有键盘快捷方式. 活动 快捷方式 书签:清除所有书签. CTRL-SHIFT-F2 书签:插入或删除书签(切换). CTRL+F2 书签:移动到下一个 ...

随机推荐

  1. 使用 ApacheBench 进行轻量级压力测试

    ApacheBench 是 Apache Http Server 附带的一个轻量级压力测试功能 先下载一个Apache Http Server :http://httpd.apache.org/ 解压 ...

  2. Dev GridView行拖拽

    http://blog.csdn.net/keyrainie/article/details/8513802 http://www.cnblogs.com/qq4004229/archive/2012 ...

  3. 用 CallerMemberName Attribute 和 EqualityComparer 统一处理类的属性值变化

    当需要实现类似 INotifyPropertyChanged 这样的接口的时候,每一个属性去判断值是否变化,然后触发事件什么的,太麻烦了,如果能用一个方法统一处理就好了. 好在真的可以做到.这个博文说 ...

  4. D3中数据与DOM element绑定之data() enter() exit()浅析

    几个非常有用的links: [1] three little circles. http://bost.ocks.org/mike/circles/ [2] How selection works.  ...

  5. 第二天ci项目规划 前后台分离

    第二天ci项目规划 前后台分离 1/31/2016 2:40:26 PM 前后台 表面上看前后台不同网站 但是数据是他们之间的联系要完成结构完整项目 设计好前后台 基于mvc框架 前后台那些地方不同 ...

  6. 0421 & SX2016

    山西省选...这个省...不算强吧...然而就是这么腊鸡题目还是wa得一无是处...怎么办啊怎么办啊...无处拯救青春和未来啊... T1: POI2004原题 BZOJ1524 n<=16.这 ...

  7. Linux tricks

    Environment Settings Path Globally set path is in /etc/profile; or the user's .bash_profile for part ...

  8. acm入门 杭电1001题 有关溢出的考虑

    最近在尝试做acm试题,刚刚是1001题就把我困住了,这是题目: Problem Description In this problem, your task is to calculate SUM( ...

  9. 【生活没有希望】NOIP2010初赛 烽火传递 smartoj1475

    整天初赛题做做,生活没有希望 用单调队列优化的dp 因为满足后来的总比先来的(在某些方面)更优 所以能用单调队列 n2变成n #include <cstdio> ],b[],c[]; in ...

  10. Windows服务安装

    运行cmd 输入:cd C:\Windows\Microsoft.NET\Framework\v4.0.30319  按回车 输入安装服务路径:如(installutil.exe D:\Project ...