浅谈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的主要工作是渲染.给 ...
随机推荐
- javascript中数组去重的4种方法
面试前端必须准备的一道问题:怎样去掉Javascript的Array的重复项.在最近面试中,百度.腾讯.盛大等都在面试里出过这个题目.这个问题看起来简单,但其实暗藏杀机. 考的不仅仅是实现这个功能,更 ...
- 轻快的VIM(三):删除
这一节我们来看看删除,删除命令比较简单,不过要使删除更有效率 你需要配合我们第一节中讲的各种移动命令 字符删除 x 删除光标所在处字符 X 删除光标所在前字符 这里没有什么可注意的地方,但需要说明一下 ...
- How to fix the sources list
How to fix the sources list Sometimes the apt-get may not work, it is often caused by the misspelled ...
- 78. Android之 RxJava 详解
转载:http://gank.io/post/560e15be2dca930e00da1083 前言 我从去年开始使用 RxJava ,到现在一年多了.今年加入了 Flipboard 后,看到 Fli ...
- Hdfs常用操作
一.linux rm是删除,不是del 二.常用操作 package hdfs; import java.io.FileInputStream; import java.io.FileNotFound ...
- 【bzoj4241】 历史研究
http://www.lydsy.com/JudgeOnline/problem.php?id=4241 (题目链接) 看到题目就联想到了[bzoj2809] Apio2012—dispatching ...
- dbm速算
经常用到,但是经常搞忘记.在这里记录一下换算的一些技巧. 为什么要用dB 在最前面,需要解释一下dB的由来,这样会让理解变得简单一点.事实上,dB(分贝)是一个纯计数单位.使用dB的目的呢,其实就是用 ...
- CF 214B Hometask(想法题)
题目链接: 传送门 Hometask Time Limit: 2 seconds Memory Limit: 256 megabytes Description Furik loves mat ...
- python deep copy and shallow copy
Python中对于对象的赋值都是引用,而不是拷贝对象(Assignment statements in Python do not copy objects, they create bindings ...
- python函数基础
一.基础 函数的定义 def 函数名(参数): ... 函数体 ... 返回值 #如果函数执行完毕也没有return语句时,自动return None. 空函数 如果想定义一个什么事也不做的空函数,可 ...