浅谈T-SQL中的派生表和CTE
引言
表表达式是一种命名的查询表达式,代表一个有效的关系表。MSSQL支持4种类型的表表达式,它们分别是:派生表、公用表表达式(CTE)、视图以及内联表值函数。表表达式并不是物理上真实存在的对象,它们是虚拟的。对于表表达式的查询在数据库引擎内部都会转化为底层对象的查询。使用表表达式通常是体现在代码的逻辑方面,而不是性能方面。下面就让我妈来详细介绍每一种类型吧。
派生表
派生表也叫表子查询是在外部查询的FROM子句中定义的。派生表的存在范围是定义它的外部查询,只要外部查询一结束,派生表也就不存在了。下面我们来看一个使用派生表的例子。
假设需要返回所有的美国客户,使用派生表我们可以这样使用。
select custid,companyname from
(select custid,companyname from
Sales.Customers
where country=N'USA') as USACusts
我们看到了派生表的简单例子。要有效的定义任何类型的表表达式,必须满足下面三个条件。
不保证有一定的顺序
表表达式代表的是一个表,关系表的中的行是没有固定顺序的。所以表表达式不允许使用ORDER BY子句。唯一例外是在T-SQL中使用了TOP选项,在带有TOP选项的查询语句中,ORDER BY子句只有一个目的,那就是为TOP选项定义要筛选出哪些行,不用于通常数据显示的目的。表表达式也符合这一法则。
所有的列必须有名称
所有的列名必须唯一
派生表的多引用
我们知道派生表是在外部查询的FROM子句中定义的,其逻辑处理顺序并不优先于外部查询。当对外部查询的FROM子句进行处理时,派生表其实并不存在。因此,如果我们要引用派生表的多个实例时,必须基于同一查询去定义多个派生表。
假设我们需要对上面的例子进行自联接,使用派生表就会显得代码冗余,如下:
use insidetsql2008
select * from
(select custid,companyname from
Sales.Customers
where country=N'USA') as USACusts
inner join (select custid,companyname from
Sales.Customers
where country=N'USA') as USACusts1
on USACusts.custid=USACusts1.custid
我们看到其实我们是对同一张表进行联接,但是需要将代码定义多遍,这无疑造成代码的混乱和冗余。
公用表表达式(CTE)
公用表表达式是和派生表很相似的一种表表达式,与派生表相比,CTE有一些重要的优势。下面还是通过一个简单的例子来看学习CTE吧
还是最上面查询所有美国客户例子。
with USACusts as (
select custid,companyname from
Sales.Customers
where country=N'USA'
)select * from USACusts
和派生表一样,一旦外部查询结束,CTE的生命周期也就结束了。
我们知道派生表在多引用的情况下,会造成代码冗余,使用公用表表达式可以缓解这方面的问题,我们来看一个例子(还是上面派生表的那个例子)。
with USACusts as (
select custid,companyname from
Sales.Customers
where country=N'USA'
)
select * from USACusts
inner join USACusts as USACusts1
on USACusts.custid=USACusts1.custid
我们看到使用公用表表达式我们无需像派生表那样定义相同的查询语句,只需要将查询语句定义一边,然后可以进行引用即可。
浅谈T-SQL中的派生表和CTE的更多相关文章
- 浅谈 django Models中的跨表
跨表操作在数据库操作非常常用,虽然其会降低读取数据的性能,但是它能节约数据在硬盘中的占用,优化数据表的结构和各自之间的关系. 在sql中,一般跨表需要用到 join 关键字 select * from ...
- 浅谈C++11中的多线程(二)
摘要 本篇文章围绕以下几个问题展开: 进程和线程的区别 何为并发?C++中如何解决并发问题?C++中多线程的基本操作 浅谈C++11中的多线程(一) - 唯有自己强大 - 博客园 (cnblogs.c ...
- SQL中 将同一个表中的A列更新到B列,B列更新到A列
有网友在SKYPE问及,如标题,SQL中 将同一个表中的A列更新到B列,B列更新到A列. 其实这个不是问题,直接写更新语句即可,可以参考下面动画演示: SQL source code: CREATE ...
- 转: 浅谈C/C++中的指针和数组(二)
转自:http://www.cnblogs.com/dolphin0520/archive/2011/11/09/2242419.html 浅谈C/C++中的指针和数组(二) 前面已经讨论了指针和数组 ...
- 转:浅谈C/C++中的指针和数组(一)
再次读的时候实践了一下代码,结果和原文不一致 error C2372: 'p' : redefinition; different types of indirection 不同类型的间接寻址 /// ...
- 转载 浅谈C/C++中的static和extern关键字
浅谈C/C++中的static和extern关键字 2011-04-21 16:57 海子 博客园 字号:T | T static是C++中常用的修饰符,它被用来控制变量的存贮方式和可见性.ext ...
- 浅谈C语言中的强符号、弱符号、强引用和弱引用
摘自http://www.jb51.net/article/56924.htm 浅谈C语言中的强符号.弱符号.强引用和弱引用 投稿:hebedich 字体:[增加 减小] 类型:转载 时间:2014- ...
- SQL中如何将一个表中的某一列的数据复制到另一个表中的某一列里
表一: SPRD PRD_NO SPC 001 NULL 002 NULL 003 NULL ... ...
- 浅谈关于QT中Webkit内核浏览器
关于QT中Webkit内核浏览器是本文要介绍的内容,主要是来学习QT中webkit中浏览器的使用.提起WebKit,大家自然而然地想到浏览器.作为浏览器内部的主要构件,WebKit的主要工作是渲染.给 ...
随机推荐
- wamp 中如何管理两个dedeCms站点
本文以WampServer2.1为例,图文说明开启wamp虚拟主机功能,也就是绑定多域名,开启多站点搭建功能. 1. 我们一键安装wamp到E盘,并可以正常启动,状态如下图所示:
- Shiro-密码的MD5加密
1.密码的加密 在数据表中存的密码不应该是123456,而应该是123456加密之后的字符串,而且还要求这个加密算法是不可逆的,即由加密后的字符串不能反推回来原来的密码,如果能反推回来那这个加密是没有 ...
- dotnet文件操作
/// <summary> /// 创建文件夹 /// </summary> /// <param name="sender"></par ...
- Android成长日记-APP的签名和打包
签名的意义: 1. 为了保证每个应用程序开发者的合法 2. 防止部分人通过使用相同的Package Name来混淆替换已经安装的程序,从而出现一些恶意篡改 3. 保证我们每次发布的版本的一致性 (如自 ...
- [NOIP2012] 提高组 洛谷P1084 疫情控制
题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都, 也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散 ...
- 用Python写了个抓图小脚本
看上这个网页上一张图了,可惜他没有提供右键另存为,看了下网页代码,是可以找到图片原始链接的!但是因为没法和现实的图片一一对应,图又多,所以找起来还是麻烦...然后,我就想用 Python 把他们全部拉 ...
- shell处理mysql增、删、改、查
引言 这几天做一个任务,比对两个数据表中的数据,昨天用PHP写了一个版本,但考虑到有的机器没有php或者php没有编译mysql扩展,就无法使用mysql系列的函数,脚本就无效了,今天写个sh ...
- AngularJs ngHref、ngSrc、ngCopy/ngCut/ngPaste
ngHref 在Angular程序没完成改变链接上用{{hash}}方式绑定的href值的时候,当用户点击该链接会跳到一个错误的页面. 格式:ng-href=”value” value:表达式. 使用 ...
- django中migration文件是干啥的
昨天很蠢的问leader git push的时候会不会把本地的数据库文件上传上去,意思是django中那些migration文件修改之后会不会上传. 然后得知不会,因为所有的数据库都存在本机的mysq ...
- 今天接触枚举类型,感觉是C里面应该才有的东西
遍历枚类型的方法: public static EActChannel getEnumByCode(int code) { for (EActChannel enm : EActChannel.val ...