1.派生表(derived table)
select YEAR(orderdate) as orderyear, COUNT(distinct custid) as numcustsfrom Sales.Ordersgroup by YEAR(orderdate);内联别名
select orderyear, COUNT(distinct custid) from (select YEAR(orderdate) as orderyear, custid from Sales.Orders) as Dgroup by orderyear外部命名
select orderyear, COUNT(distinct custid) from (select YEAR(orderdate), custid from Sales.Orders) as D(orderyear,custid)group by orderyear;2.公用表表达式(CTE, common table express)
with C(orderyear, custid) as(select YEAR(orderdate), custidfrom Sales.Orders)select orderyear, COUNT(distinct custid) as numcustsfrom Cgroup by orderyear;with C1 as
(select YEAR(orderdate) as orderyear, custidfrom Sales.Orders),C2 as(select orderyear, COUNT(distinct custid) as numcustsfrom C1group by orderyear)select orderyear, numcustsfrom C2where numcusts > 70嵌套CTE
with <CTE_Name>[<target_column_list>]as(<anchor_member>union all<recursive_member>)<outer_query_against_CTE>with EmpsCTE as
(select empid, mgrid, firstname, lastnamefrom HR.Employeeswhere empid = 2union allselect C.empid, C.mgrid, C.firstname, C.lastnamefrom EmpsCTE as P --这里的引用前一结果集join HR.Employees as Con C.mgrid = P.empid)select empid, mgrid, firstname, lastnamefrom EmpsCTE option(maxrecursion 5); -- 这里的引用返回所有结果集3.视图
use TSQLFundamentals2008if object_id('Sales.USACusts') is not nulldrop view Sales.USACusts;gocreate view Sales.USACustsas select custid, companyname, contactname, contacttitle, address, city, region, postalcode, country, phone, taxfrom Sales.Customerswhere country = N'USA';go在定义表表达式的查询语句中不允许出现order by子句,因此视图定义中也不允许出现。确实须要从视图中返回有序的数据行,应该在使用视图的外部查询中指定一个数据展示用的order by子句。即使使用TOP选项,视图定义中的order by子句只是确保为TOP选项提供逻辑筛选服务,如果查询视图时没有在外部查询中指定order by子句,则仍然无法保证结果集中行的顺序。
alter view Sales.USACustsasselect top(100) percent custid, companyname, contactname, contacttitle, address, city, region, postalcode, country, phone, taxfrom Sales.Customerswhere country = N'USA'order by region;goselect custid, companyname, region from Sales.USACusts; --并不能总能产生按region列进行排序的结果
encryption选项
select object_definition(object_id('Sales.USACusts')); --can get definition of the viewalter view Sales.USACusts with encryption
asselect custid, companyname, contactname, contacttitle, address, city, region, postalcode, country, phone, taxfrom Sales.Customerswhere country = N'USA';goselect object_definition(object_id('Sales.USACusts')); -- can not get definition of the view
schemabinding 选项
alter view Sales.USACusts with schemabindingasselect custid, companyname, contactname, contacttitle, address, city, region, postalcode, country, phone, taxfrom Sales.Customerswhere country = N'USA';goalter table Sales.Customers drop column address; -- error message
check option 选项
alter view Sales.USACusts with check optionasselect custid, companyname, contactname, contacttitle, address, city, region, postalcode, country, phone, taxfrom Sales.Customerswhere country = N'USA';goinsert into Sales.USACusts
values (..., 'UK', ...); --error message, not 'USA'4.内联表值函数(inline TVF, inline table-valued function)--参数化的视图
use TSQLFundamentals2008if object_id('dbo.fn_GetCustOrders') is not nulldrop function dbo.fn_GetCustOrders;gocreate function dbo.fn_GetCustOrders(@cid as int) returns tableasreturn select orderid, custid, empid, orderdate, requireddate, shippeddate, shipperid, freight, shipname, shipaddress, shipcity, shipregion, shippostalcode, shipcountryfrom Sales.Orderswhere custid = @cid;goselect C.orderid, C.custid, D.productid, D.qty
from dbo.fn_GetCustOrders(1) as Cjoin Sales.OrderDetails as Don C.orderid = D.orderid;5.Apply运算符
包括cross apply与outer apply。cross apply与cross join类似,都是用右表表达式应用到左表中的每一行。与join不同的是,使用cross apply操作符时,对于左表中的每一行,右表表达式可能代表不同的数据行集合。为此,可以在右边使用一个派生表,在派生表的查询中去引用左表列;也可以使用内联表值函数,把左表中的列作为输入参数进行传递。cross apply在右表为空时不显示左表的行,outer apply则显示左表的行,同时右表同一行的列用null替代。cross apply:
select C.custid, A.orderid, A.orderdatefrom Sales.Customers as Ccross apply (select top(3) orderid, empid, orderdate, requireddatefrom Sales.Orders as Owhere O.custid = C.custidorder by orderdate desc, orderid desc) as Aouter apply:
select C.custid, A.orderid, A.orderdatefrom Sales.Customers as Couter apply (select top(3) orderid, empid, orderdate, requireddatefrom Sales.Orders as Owhere O.custid = C.custidorder by orderdate desc, orderid desc) as A