本系列【T-SQL基础】主要是针对T-SQL基础的总结。
【T-SQL基础】01.单表查询-几道sql查询题
【T-SQL基础】02.联接查询
【T-SQL基础】03.子查询
【T-SQL基础】04.表表达式-上篇
【T-SQL基础】04.表表达式-下篇
【T-SQL基础】05.集合运算
【T-SQL基础】06.透视、逆透视、分组集
【T-SQL基础】07.数据修改
【T-SQL基础】08.事务和并发
【T-SQL基础】09.可编程对象
?----------------------------------------------------------
【T-SQL进阶】01.好用的SQL TVP~~独家赠送[增-删-改-查]的例子
?----------------------------------------------------------
【T-SQL性能调优】01.TempDB的使用和性能问题
【T-SQL性能调优】02.Transaction Log的使用和性能问题
【T-SQL性能调优】03.执行计划
【T-SQL性能调优】04.死锁分析
持续更新......欢迎关注我!
概述:
本篇主要是对表表达式中派生表和公用表表达式基础的总结。
表表达式包含四种:
1.派生表
2.公用表表达式
3.视图
4.内联表值函数
本篇是表表达式的上篇,只会讲到派生表和公用表表达式,下篇会讲到视图和内联表值函数。
下面是表表达式的思维导图:
? 
?
表表达式:
1.一种命名的查询表达式,代表一个有效的关系表。
2.可以像其他表一样,在数据处理语句中使用表表达式。
3.在物理上不是真实存在的什么对象,它们是虚拟的。对于表达式的查询在数据库引擎内部都将转化为对底层对象的查询。
为什么使用表表达式:
1.使用表表达式的好处是逻辑方面,在性能上没有提升。
2.通过模块化的方法简化问题的解决方案,规避语言上的某些限制。在外部查询的任何字句中都可以引用在内部查询的SELECT字句中分配的列别名。比如在SELECT字句中起的别名,不能在WHERE,group by等字句(逻辑顺序位于SELECT字句之前的字句)中使用,通过表表达式可以解决这类问题。
一、派生表
1.用法:
使用地方:外部查询的FROM字句中定义
存在范围:外部查询一结束,派生表就不存在
语法:派生表的查询语句写在括号里面,括号外面跟着AS关键字和派生表的名称。
SELECT columns FROM?( SELECT columns FROM Table ) AS TABLE_1
例子:
|
1
2
3
4
5
SELECT
??
*
FROM
????
(?
SELECT
????
orderdate
??????????
FROM
??????
Sales.Orders
WHERE
?????
orderdate =?
'20070101'
????????
)?
AS
?
O1

?
定义了一个O1的派生表,返回所有订单日期='20070101'的订单,外部查询返回派生表的所有行。
在这个例子中,其实不需要派生表,只是为了演示派生表的语法。
注意:
要有效定义任何类型的表表达式,查询语句必须满足三个要求:
(1)不保证有一定的顺序。
表表达式是一个表,而关系表中的行驶没有固定顺序的,所以?ANSI SQL?不允许表表达式查询语句中出现ORDER BY字句。除非另外还指定了?TOP?或?FOR XML,否则,ORDER BY?子句在视图、内联函数、派生表、子查询和公用表表达式中无效。
(2)所有的列必须有名称
(3)所有的列必须是唯一的
当表表达式的查询联接了两个表,而这两个表存在名称相同的列时,就会出现相同名称的列,如果要使表达式有效,则必须使这两个表的列名不一样。
3.分配列别名
例子:
下面的SQL语句是无效的:
3
SELECT??
YEAR
(orderdate)?
orderyear
Sales.Orders
GROUP?
BY
?
orderyear
方案一:SELECT字句和GROUP BY字句中都定义YEAR(orderdate)
BY?
(orderdate)
方案二:派生表
因为GROUP BY语句的是在SELECT字句之前执行的,所以GROUP BY字句不能引用SELECT字句中定义的别名orderyear。
解决办法是使用表表达式:
5
6
SELECT????
orderyear
O1
?
orderyear
结果:

派生表O1是字段orderyear的集合,外部查询SELECT字句和GROUP BY字句可以引用派生表O1的orderyear字段。
SQL SERVER在执行时会扩展表表达式的定义,以便直接访问底层对象。扩展后,与方案一类似。
一般来说,表表达式既不会对性能产生正面影响,也不会对性能产生负面影响。
3.使用参数
在派生表的查询中,可以引用参数。
基于上面的例子,我们定义了一个标量@orderid,在派生表查询语句中的WHERE字句中引用这个参数。
6
7
8
DECLARE
?
@orderid?
AS
?
INT
?
= 10248
?????????
orderyear
SELECT????????????
Sales.Orders
WHERE
?
orderid = @orderid
O1
orderyear
4.嵌套
如果须要用一个本身就引用了某个派生表的查询去定义另一个派生表,最终得到的就是嵌套派生表。
例子:查询用于返回订单年份和该年处理的客户数,要求每个订单年份处理的客户数要多于10人
方案一:我们用第一节中单表查询查询出结果
?
orderyear,
????????
COUNT
(
DISTINCT
?
custid)?
numcuts
Sales.Orders
(orderdate)
HAVING??
custid) > 10
方案二:嵌套派生表
8
9
10
11
????????????????????
numcuts
????????????????????????????????
custid
??????????????????????
Sales.Orders
????????????????????
O1
BY??
orderyear
O2
WHERE???
numcuts > 10
嵌套查询看起来非常复杂,嵌套查询也是很容易产生问题的一个方面。在这个例子中,使用嵌套派生表的目的是为了重用列别名。但是,由于嵌套增加了代码的复杂性,所以对于本例考虑使用方案一。
5.练习题
1.写一个查询,为每个雇员返回其订单日期最近的所有订单(用派生表)
期望结果:

本题分两个步骤:
1.可以先查询出每个雇员的订单的最大日期,生成派生表O1
2.O1与Sales.Orders表进行关联,查询出每个雇员处理过的订单日期等于最大的订单日期的所有订单。
O2.empid,monospace!important; min-height:auto!important'>O2.orderdate,
orderid,monospace!important; min-height:auto!important'>custid
empid,monospace!important; min-height:auto!important'>????????????????????
MAX
orderdate
empid
O1
????????
INNER
?
JOIN
?
Sales.Orders?
O2?
ON
?
O1.empid = O2.empid
?????????????????????????????????????????
AND
?
O1.orderdate = O2.orderdate
二、公用表表达式
公用表表达式是和派生表相似的另一种形式的表表达式,但是公用表表达式具有一些优势。
1.语法:
内联格式:别名写在内部查询中
11
12
13
14
WITH?
表名
AS
(
????
内部查询
)
外部查询<br>
例子:
AS
(
????
SELECT
?
custid,companyname?
FROM
?
Sales.Customers
)
?
*?
外部查询
?
例子:
O1(custid_1,companyname_1)
AS
(
Sales.Customers
)
O1
2.用法
公用表表达式和派生表一样,前面需要遵守的规则对公用表表达式同样适用。当外部查询结束,公用表表达式的生命周期就结束了。
和派生表一样,可以引用参数。
9
@custid?
= 10248;
?
?
AS
(
Sales.Customers
@custid = @custid
)
O1
4.定义多个CTE
CTE和派生表相关具有以下优势:
如果要在一个CTE中引用另一个CTE,不须要像派生表那样进行嵌套,只需要在同一个WITH字句中定义多个CTE,并用逗号把它们分隔开。每个CTE可以引用在它前面定义的所有CTE,而外部查询则可以引用所有CTE。
如下面的例子,将嵌套派生表改为多个CTE:
14
15
16
C1?
AS
(
????????????
Sales.Orders
),
C2?
AS
(
????????????
numcusts
C1
orderyear
numcusts
C2
为每个订单按照orderdate、orderid的顺序来计算其行号,并返回行号在11~20之间的行。

1.查询出基于orderdate,orderid排序的结果集,然后将这个查询语句用CTE来表示
2.查询第一步结果集中11~20之间的行
O1
ROW_NUMBER() OVER (?
ORDER
?
rownum
Sales.Orders
)???
??
*
O1
rownum?
BETWEEN
?
11?
20
?
参考资料:
《SQL2008技术内幕:T-SQL语言基础》
?
?原文来自:基础很重要~~04.表表达式-上篇
作 者:?Jackson0714?
出 处:http://www.cnblogs.com/jackson0714/?
关于作者:专注于微软平台的项目开发。如有问题或建议,请多多赐教!?
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。?
特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信我?
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是作者坚持原创和持续写作的最大动力!?
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!