1、派生表
實質:就是特殊的子查詢(將查詢結果放在from后面)
含有一張Order表:
看下面的sql語句:
select
orderid,orderdate,custid
from
(
select
orderid,orderdate,custid,ROW_NUMBER() over(order by orderid) as rownum--列明必須起別名
from [Sales.Orders]
) as t--表名必須起別名
需要注意的特殊之處:查詢出來的表要起別名,子查詢里面的字段名也要起別名
2、CTE(公共表的表達式)
1)語法規范:
with use_country--定義的表名
as--上面的是 語法:
(
select country,companyname,custid
from [Sales.Customers]
where country='按時打算'
)
select * from use_country;--將查詢語句 寫在 子查詢的后面
將查詢語句放在最后。
下面看幾個例子,具體解析一下:
業務邏輯:還是用上面的那張Order表,要求:查詢出 每年的訂單數量 大于10的 用戶
1》普通的寫法:
select
custid,year(orderdate),COUNT(1) as '訂單數量'
from [Sales.Orders]
group by YEAR(orderdate), custid
having COUNT(orderid)>10 --having:對 group by 之后的 組函數 進行 篩選使用
2》使用派生表:
select
custid,orderyear,orderNum
from
(
select
custid,orderyear,COUNT(*) as orderNum
from
(
select
custid, year(orderdate) as orderyear
from [Sales.Orders]
) as t1
group by orderyear,custid
) as t2
where orderNum>10
上面的 查詢的層次只有兩層,如果層次非常多的話,就會出現,看起來非常費勁了,所以使用CTE的方式更簡潔
with OrderYear
as
(
select
custid,YEAR(orderdate) as orderyear
from [Sales.Orders]
),
OrderGroupYear
as
(
select
custid,orderyear,COUNT(orderyear) as ordernum
from OrderYear
group by orderyear,custid
),
OrderNumThanTen
as
(
select
custid,orderyear,ordernum
from OrderGroupYear
where ordernum>10
)
select * from OrderNumThanTen;
2)CTE還可以多張表引用:(相當于c#里面的將重復的代碼封裝成一個方法)下面舉例:
業務邏輯:查詢出 每年 客戶的數量,以及 前后兩年之間客戶數量的差量
--首先查詢出每年叫客戶的數量:
select
year(orderdate),COUNT(distinct custid)--將 重復的 客戶 要去掉
from [Sales.Orders]
group by YEAR(orderdate)
然后使用派生表的方式實現:
select
currtYearOrder.orderYear,currtYearOrder.custCount,prevYearOrder.orderYear,prevYearOrder.custCount,currtYearOrder.custCount-prevYearOrder.custCount
from
(
select
year(orderdate) as orderYear,COUNT(distinct custid) as custCount--將 重復的 客戶 要去掉
from [Sales.Orders]
group by YEAR(orderdate)
) as currtYearOrder
left outer join
(
select
year(orderdate) as orderYear ,COUNT(distinct custid) as custCount--將 重復的 客戶 要去掉
from [Sales.Orders]
group by YEAR(orderdate)
) as prevYearOrder
on currtYearOrder.orderYear=prevYearOrder.orderYear+1
下面使用CTE的方式實現,就不用重復:
with OrderYearCust
as
(
select
year(orderdate) as orderYear,COUNT(distinct custid) as custCount--將 重復的 客戶 要去掉
from [Sales.Orders]
group by YEAR(orderdate)
)
select
curtYearOrder.orderYear,curtYearOrder.custCount,prevYearOrder.orderYear,prevYearOrder.custCount,curtYearOrder.custCount-prevYearOrder.custCount
from OrderYearCust as curtYearOrder left outer join OrderYearCust as prevYearOrder on curtYearOrder.orderYear=prevYearOrder.orderYear+1
3)CTE遞歸查詢:(針對 樹形節點 進行查詢)
表的結果如下:
業務邏輯:需要查詢出 mgrid 為 2 下面的 所有的子節點
with diguiEmployee
as
(
--起點:最上層的 查詢(只執行一次)
select
enpid,lastname,firstname,mgrid
from [HR.Employees]
where mgrid=6
union all --連接 起點:上層查詢 和遞歸查詢
--遞歸查詢
select
e.enpid,e.lastname,e.firstname,e.mgrid
from [HR.Employees] as e inner join diguiEmployee as d
on e.mgrid=d.enpid
)
select enpid,lastname,firstname,mgrid from [HR.Employees] where enpid=6
union all --將查詢的 結果 連接 起來
select * from diguiEmployee;