概述

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

目录

  • 概述
  • 流程图
  • 步骤分解
    • 测试数据
    • FROM阶段
    • WHERE阶段
    • GROUP BY阶段
    • HAVING阶段
    • SELECT阶段
    • ORDER BY阶段
    • TOP于ORDER BY的关系
  • 总结

流程图

 (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 NULLCONSTRAINT [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/p/4168193.html,如需转载请自行联系原作者

SQL Server 查询分解相关推荐

  1. Mysql与Sql Server查询数据库中表以及表字段

    1.查询数据库表信息 mysql查询数据库中所有表信息 SELECTtable_name AS '表名',table_comment AS '说明',create_time AS '创建时间',upd ...

  2. SQL Server 查询性能优化——覆盖索引(二)

    在SQL Server 查询性能优化--覆盖索引(一)  中讲了覆盖索引的一些理论. 本文将具体讲一下使用不同索引对查询性能的影响. 下面通过实例,来查看不同的索引结构,如聚集索引.非聚集索引.组合索 ...

  3. SQL Server查询所有数据库下模式schema

    SQL Server查询所有数据库下模式名 需求描述 找到SQL Server里所有数据库下的schema.输出格式为数据库名.模式名. 背景补充 关于SQL Server需要简单介绍下,从数据库对象 ...

  4. SQL SERVER查询时间条件式写法

    如下表: tid    tname     tdate     1      张三      2009-10-29 19:04:50     2      李四      2006-11-12 11: ...

  5. 如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集

    如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?(2006-12-14 09:25:36) 与这个问题具有相同性质的其他描述还包括: 如 ...

  6. SQL Server查询中特殊字符的处理方法

    来源:http://database.51cto.com/art/201009/227766.htm SQL Server查询中,经常会遇到一些特殊字符,比如单引号"'"等,这些字 ...

  7. sql查询oracle数据,sql-server – 从SQL Server查询Oracle数据库

    我有一个Oracle 11g XE数据库,我想将其转移到SQL Server Express 2005中. 起初我以为我只是在Oracle中生成表作为SQL,操纵数据格式,并在SQL Server中运 ...

  8. sqlserver 指定的网络名不再可用_50个比较实用的SQL Server查询语句(1)

    在本文中,我将解释一些通用的SQL查询.我认为每个开发人员都应该了解这些查询.这些查询与SQL的任何特定主题都无关.但是了解这些查询可以解决一些复杂的任务,并且可以在许多场景中使用. 查询1:检索所有 ...

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

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

最新文章

  1. P3806 【模板】点分治1
  2. float类型为什么不精确等于0_程序中算钱不能用浮点类型是个什么坑?
  3. WCF中的Stream操作
  4. Redis各特性的应用场景
  5. kakfa中的ISR解释
  6. Entity Framework Core 2.0 全局查询过滤器
  7. hdu4965-Fast Matrix Calculation【矩阵乘法】
  8. 阿里MySQL读写一致_缓存与数据库读写一致的解决方案
  9. opencv检测相交点_OpenCV学习18--霍夫变换检测直线
  10. U盘检测及量产工具大合集
  11. Appium自动化测试原理
  12. 计算机中振荡器作用,振荡器工作原理介绍
  13. 魔兽世界6.2.2德拉诺怎么飞行 wow飞行成就获得方法
  14. 如何用HBuilderX把uni-app项目运行到微信开发者工具上
  15. 【计算机体系结构实验】指令调度和延迟分支
  16. 不能装载文档控件。请在检查浏览器的选项中检查浏览器的安全设置_网络安全科普 | 如何正确设置浏览器!...
  17. Win10 或者Win7 64位系统安装32位的CAD2010教程
  18. epub格式电子书剖析之三:NC…
  19. 中国程序员VS美国程序员,太形象了...
  20. 从一个“信用卡”类理解python面向对象编程的核心概念

热门文章

  1. 传奇3服务器数据修改,传奇3游戏架设技术之3.0服务器架设和设置攻略详细分享...
  2. soc 设计soc设计 uml实务手册_企业内训“领域建模和领域驱动设计”训练方案(2020年)...
  3. AVS3变换系数编码:SRCC
  4. U8销售出库单API接口 --参照发货通知单
  5. 微信运动刷步软件是真的吗?微信运动刷步软件有用吗?
  6. 【C】96.实现一个函数,可以旋字符串中的k个字符
  7. 离散数学---判断矩阵:自反性,反自反性,对称性得到矩阵的自反闭包,对称闭包。
  8. redis集群介绍与搭建
  9. 段码屏中液晶相与相变的含义?
  10. 矩阵的转置(c++)