sql之表的表達式

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;
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容