T-sql语句查询执行顺序

前言

数据库的查询执行,毋庸置疑是程序员必备技能之一,然而数据库查询执行的过程绚烂多彩,却是很少被人了解,今天哥哥要带你装逼带你飞,深入一下这sql查询的来龙去脉,为查询的性能优化处理打个基础,或许面试你也会遇到,预防不跪还是看看吧。

这篇博客,摒弃查询优化性能,作为其基础,只针对查询流程讲解剖析。

本片博客阐述的过程为

1、上一个标识过的sql语句,展示查询执行的流程

2、上一个流程图

3、做一个例子逐步深入分析,帮助理解

4、做一个装逼的总结

sql查询语句的处理步骤,代码清单

--查询组合字段
(5)select (5-2) distinct(5-3) top(<top_specification>)(5-1)<select_list>
--连表
(1)from (1-J)<left_table><join_type> join <right_table> on <on_predicate>
        (1-A)<left_table><apply_type> apply <right_table_expression> as <alias>
        (1-P)<left_table> pivot (<pivot_specification>) as <alias>
        (1-U)<left_table> unpivot (<unpivot_specification>) as <alias>
--查询条件
(2)where <where_pridicate>
--分组
(3)group by <group_by_specification>
--分组条件
(4)having<having_predicate>
--排序
(6)order by<order_by_list>

说明:

1、顺序为有1-6,6个大步骤,然后细分,5-1,5-2,5-3,由小变大顺序,1-J,1-A,1-P,1-U,为并行次序。如果不够明白,接下来我在来个流程图看看。

2、执行过程中也会相应的产生多个虚拟表(下面会有提到),以配合最终的正确查询。

sql查询语句的处理步骤,流程图

 

实例准备,创建表,插入数据,写要分析的实例查询语句

1、首先创建2各表

2、创建两个表,并插入表数据,脚本如下 

USE [test]
GO
/****** Object:  Table [dbo].[Member]    Script Date: 2014/12/22 14:05:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Member](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [nvarchar](30) NULL,
    [phone] [varchar](15) NULL,
 CONSTRAINT [PK_MEMBER] PRIMARY KEY CLUSTERED 
(
    [id] 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
SET ANSI_PADDING OFF
GO
/****** Object:  Table [dbo].[Order]    Script Date: 2014/12/22 14:05:17 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Order](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [member_id] [int] NULL,
    [status] [int] NULL,
    [createTime] [datetime] NULL,
 CONSTRAINT [PK_ORDER] PRIMARY KEY CLUSTERED 
(
    [id] 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
SET IDENTITY_INSERT [dbo].[Member] ON 

GO
INSERT [dbo].[Member] ([id], [Name], [phone]) VALUES (1, N'张龙豪', N'18501733702')
GO
INSERT [dbo].[Member] ([id], [Name], [phone]) VALUES (2, N'Jim', N'15039512688')
GO
INSERT [dbo].[Member] ([id], [Name], [phone]) VALUES (3, N'Tom', N'15139512854')
GO
INSERT [dbo].[Member] ([id], [Name], [phone]) VALUES (4, N'Lulu', N'15687425583')
GO
INSERT [dbo].[Member] ([id], [Name], [phone]) VALUES (5, N'Jick', N'13528567445')
GO
SET IDENTITY_INSERT [dbo].[Member] OFF
GO
SET IDENTITY_INSERT [dbo].[Order] ON 

GO
INSERT [dbo].[Order] ([id], [member_id], [status], [createTime]) VALUES (1, 1, 3, CAST(0x0000A40900B3BBFB AS DateTime))
GO
INSERT [dbo].[Order] ([id], [member_id], [status], [createTime]) VALUES (2, 2, 1, CAST(0x0000A40900B3CEF2 AS DateTime))
GO
INSERT [dbo].[Order] ([id], [member_id], [status], [createTime]) VALUES (3, 3, 4, CAST(0x0000A40900B3D2D0 AS DateTime))
GO
INSERT [dbo].[Order] ([id], [member_id], [status], [createTime]) VALUES (4, 4, 0, CAST(0x0000A40900B3D660 AS DateTime))
GO
INSERT [dbo].[Order] ([id], [member_id], [status], [createTime]) VALUES (5, 5, 1, CAST(0x0000A40900B3D9B9 AS DateTime))
GO
INSERT [dbo].[Order] ([id], [member_id], [status], [createTime]) VALUES (6, 6, 2, CAST(0x0000A40900B3DFEA AS DateTime))
GO
INSERT [dbo].[Order] ([id], [member_id], [status], [createTime]) VALUES (7, NULL, 0, CAST(0x0000A40900E34971 AS DateTime))
GO
SET IDENTITY_INSERT [dbo].[Order] OFF
GO
ALTER TABLE [dbo].[Order] ADD  DEFAULT (getdate()) FOR [createTime]
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'编号' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Member', @level2type=N'COLUMN',@level2name=N'id'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'姓名' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Member', @level2type=N'COLUMN',@level2name=N'Name'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'电话' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Member', @level2type=N'COLUMN',@level2name=N'phone'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'会员表' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Member'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'编号' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Order', @level2type=N'COLUMN',@level2name=N'id'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'会员编号' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Order', @level2type=N'COLUMN',@level2name=N'member_id'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'订单状态' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Order', @level2type=N'COLUMN',@level2name=N'status'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'下单日期' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Order', @level2type=N'COLUMN',@level2name=N'createTime'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'订单表' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Order'
GO
View Code 

3、编写咱们要解析的查询语句,即本篇要查询的实例语句。

select top(4)  status , max(m.id) as maxMemberID
from [dbo].[Member] as m right outer join [dbo].[Order] as o 
on m.id=o.member_id 
where m.id>0
group by status having status>=0 order by maxMemberID asc

实例语句分步骤分析

第一步,从from开始。

1.1、加载左表

from [dbo].[Member] as m 

查询结果:member表中的所有数据

1.2、这里应该是 right outer join ,但是这里在sql中被定义分解为2个步骤,即join ,right outer join 。表达式关键字从左到右,依次执行。

join [dbo].[Order] as o 

查询结果:存入虚拟表vt1,为两个表的笛卡尔集合。这里你或许不明白什么叫笛卡尔集合,我打个比方给说说,还望不要嫌弃,就是小朋友握手问题,A班里有3个学生(看作一个表的三条数据),B班里有2个学生(看作另外一个表的2条数据).B班小朋友跟A班小朋友搞联欢晚会,首先要每个人都要确保跟另外一个班的同学我一下手,那么交叉出来的集合就是(2*3=6)有6条不同的轨迹。这个轨迹的集合就是笛卡尔集合。如果你还不明白,我再说下,就是m(5条数据)表中的第一条数据跟o(7条数据)表中的所有数据握下手,有7条,然后依次类推共有35条不同的数据。这里的null值也是要加进来的。

1.3、on 筛选器

on m.id=o.member_id 

查询结果:从上一步的笛卡尔集合35条数据中删除掉不匹配的行,就得到啦5条数据,存入虚拟表Vt2

1.4、添加外部行(outer row)

right outer join [dbo].[Order] as o 

查询结果为:右表(order)作为保留表,把剩余的数据重新添加到上一步的虚拟表中vt2,生成虚拟表vt3.

第二部,进入where阶段

where m.id>0

查询结果:存入虚拟表vt4,为筛选的条件为true的结果集,这里加入一个记忆点,就是,where的筛选删除为永久的,而on的筛选删除为暂时的,因为on筛选过后,有可能会经过outer添加外部行,重新把数据加载回来,而where则不能。

第三部,group by分组

group by status

查询结果:存入vt5,以status列的数值开始分组,即status列,值一样的分为一组,这里的两个null在三值逻辑中被视为true。三值逻辑:true,false,null。此三值,null为未知,是数据的逻辑特色,有的地方两个null相等为ture,在有些地方则为false。这个你百度下看看有很多讲解。

 第四步,having筛选器

having status>=0 

查询结果:筛选分好组的组数据,把不满足条件的删除掉

第五步,select查询挑拣计算列

5.1、计算表达式

select status , max(m.id)

查询结果:从分过组的数据中计算各个组中的最大m.id,列出要筛选显示的列。

5.2、distinct过滤重复

5.3、top 结合order by 筛选 多少行,但这里的数据没有排序只是把多少行数据列出来而已。

第六部,order by 排序显示。

蛋疼的总结,装逼是有依据的

本篇博客参考:《Microsoft SQL Server 2008技术内幕:T-SQL查询》,感谢阅读,(C#).NET技术分享QQ群: 232458226,欢迎加入。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQL查询一 实验学时:2   实验类型:验证 实验要求:必修 一、实验目的 通过本实验使学生掌握单表查询并初步掌握多表查询的技能。 二、实验内容 使用实验一建立的银行贷款数据库和表,完成以下查询。 1-10题为单表查询,11-25为多表查询查询所有法人的法人代码、法人名称、经济性质和注册资金。 查询“B1100”银行的的银行名称和电话。 查询贷款金额在2000至4000万元之间的法人代码、银行代码、贷款日期和贷款金额。 查询2009年1月1日以后贷款且贷款期限是10年的法人代码。 查询贷款期限为5年、10年或15年的贷款信息。 查询经济性质为“私营“的所有法人的最高注册资金、最低注册资金和平均注册资金。 查询每种经济性质的法人的经济性质、最高注册资金、最低注册资金和平均注册资金。 统计每个法人的法人代码和贷款总次数,要求查询结果按贷款总次数的升序排列。 查询贷款次数超过3次的法人的平均贷款金额和贷款次数。  统计每种经济性质贷款的法人的总数和其平均贷款金额,列出平均贷款金额前三名的经济性质、法人总数和平均贷款金额。  查询贷款期限为5年、10年或15年的法人名称、银行名称、贷款日期、贷款金额和贷款期限。  查询经济性质为“国营”的法人在“上海”的银行贷款的信息,列出法人名称、银行名称和贷款日期。  查询与“B1100”银行在同一城市(假设银行名称的第5和第6个字符为城市名称)的其他的银行的名称。  查询哪些银行没有贷过款,列出银行号和银行名称。分别用多表连接和子查询两种方式实现。  查询贷过款的所有法人的名称,贷款银行名称,贷款日期,贷款金额,要求将查询结果放在一张新的永久表New_LoanT中,新表中的列名分别为:法人名称、银行名称、贷款日期和贷款金额。  分别查询经济性质“国营”和“私营”的法人名称,贷款银行名称,贷款日期,贷款金额,要求将这两个查询结果合并成一个结果集,并以法人名称、银行名称、贷款日期和贷款金额作为显示列名,结果按贷款日期的升序和贷款金额的降序显示。 使用实验一建立的学生数据库和表,完成以下查询 查询计算机系没有选课的学生的姓名和年龄。 统计‘VB’课程的考试最高分、最低分和平均分。 统计‘数据库’课程的选课人数。 统计计算机系学生’vb’课程考试的最高分、最低分、平均分。  统计每个系学生’vb’课程考试的最高分、最低分、平均分,列出系名和三个分数。 查询每个学生的修课总学分,并进行如下处理:如果总学分高于10分,则显示‘好学生’;如果总学分在6到10分间,则显示‘一般学生’;如果总学分低于6分,则显示‘不好学生’。 统计每个系每个学生的修课门数和平均成绩,如果修课门数大于3并且平均成绩高于90的显示‘优秀’;如果修课门数大于3并且平均成绩在80~90,则显示‘较好’;对于修课门数小于等于3的并且平均成绩高于90的显示‘较好’;如果修课门数小于等于3并且平均成绩在80~90,则显示‘一般’;其他情况显示为‘应努力’。列出系名、学号、原修课门数和平均成绩以及处理后的显示结果。 查询计算机系学生考试成绩最低的两个成绩所对应的学生的姓名、课程名和成绩。 列出没有选课的学生的学号、姓名和所在系。 三、思考题 1、创建表: 教师表(   tid 普通编码定长字符型,长度为10,主关键字   tname 普通编码定长字符型,长度为10,非空 zc 普通编码定长字符型,长度为6) 设此表数据如下: tid Tname zc T1 A 教授 T2 B 副教授 T3 C 教授 编写SQL语句,使查询的结果显示为如下形式: 教师号 教师名 教授 副教授 T1 A 教授 T2 B 副教授 T3 C 教授 2、创建表: 教师表(   tid 普通编码定长字符型,长度为10,主码   tname 普通编码定长字符型,长度为10,非空 zc 普通编码定长字符型,长度为6 Salary 工作,整型) 设此表数据如下: tid Tname zc Salary T1 A 教授 5000 T2 B 副教授 4000 T3 C 教授 5000 编写SQL语句,使查询的结果显示为如下形式: 教师号 教师名 教授工资 副教授工资 T1 A 5000 Null T2 B Null 4000 T3 C 5000 Null 四、实验报告 将实验结果反映在实验报告中,并对实验中遇到的问题及解决方案进行整理、分析总结,提出实验结论或自己的看法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值