sqlserver中cross apply與outer apply用法

apply有兩種形式: cross apply 和 outer apply

先看看語法:

  <left_table_expression>  {cross|outer} apply <right_table_expression>

再讓我們瞭解一下apply運算涉及的兩個步驟:

  1. A1:把右表表達式(<right_table_expression>)應用到左表(<left_table_expression>)輸入的行;
  2. A2:添加外部行;

  使用apply就像是先計算左輸入,讓後爲左輸入中的每一行計算一次右輸入。(這一句很重要,可能會不理解,但要先記住,後面會有詳細的說明

最後結合以上兩個步驟說明cross apply和outer apply的區別:

  cross apply和outer apply 總是包含步驟A1,只有outer apply包含步驟A2,如果cross apply左行應用右表表達式時返回空積,則不返回該行。而outer apply返回改行,並且改行的右表表達式的屬性爲null。

看到上面的解釋或步驟大家可能還是一頭的霧水,不知所云。下面用例子來說明:

先建表一([dbo].[Customers]  字段說明:customerid -- 消費者id , city -- 所在城市):

 

複製代碼

複製代碼

CREATE TABLE [dbo].[Customers](
    [customerid] [char](5) COLLATE Chinese_PRC_CI_AS NOT NULL,
    [city] [varchar](10) COLLATE Chinese_PRC_CI_AS NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [customerid] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

複製代碼

複製代碼

 

向表一插入數據:

insert into dbo.Customers values('FISSA','Madrid');
insert into dbo.Customers values('FRNDO','Madrid');
insert into dbo.Customers values('KRLOS','Madrid');
insert into dbo.Customers values('MRPHS','Zion');

查詢所插入的數據:

select * from dbo.Customers

結果如圖:

再建表二([dbo].[Orders]  字段說明:orderid -- 訂單id  , customerid -- 消費者id):

複製代碼

複製代碼

CREATE TABLE [dbo].[Orders](
    [orderid] [int] NOT NULL,
    [customerid] [char](5) COLLATE Chinese_PRC_CI_AS NULL,
PRIMARY KEY CLUSTERED 
(
    [orderid] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

複製代碼

複製代碼

向表二插入數據:

複製代碼

複製代碼

insert into dbo.Orders values(1,'FRNDO');
insert into dbo.Orders values(2,'FRNDO');
insert into dbo.Orders values(3,'KRLOS');
insert into dbo.Orders values(4,'KRLOS');
insert into dbo.Orders values(5,'KRLOS');
insert into dbo.Orders values(6,'MRPHS');
insert into dbo.Orders values(7,null);

複製代碼

複製代碼

查詢插入的數據:

select * from dbo.orders

結果如圖:

例子:題目:得到每個消費者最新的兩個訂單:

用cross apply

sql:

複製代碼

複製代碼

select *
from dbo.Customers as C
 cross apply
    (select top 2 *
     from dbo.Orders as O
     where C.customerid=O.customerid
     order by orderid desc) as CA

複製代碼

複製代碼

結果如圖:

過程分析:

  它是先得出左表【dbo.Customers】裏的數據,然後把此數據一條一條的放入右表表式中,分別得出結果集,最後把結果集整合到一起就是最終的返回結果集了(T1的數據 像for循環一樣 一條一條的進入到T2中 然後返回一個集合  最後把所有的集合整合到一塊  就是最終的結果),最後我們再理解一下上面讓記着的話(使用apply就像是先計算左輸入,讓後爲左輸入中的每一行計算一次右輸入)是不是有所明白了。

實驗:用outer apply 試試看看的到的結果:

sql語句:

複製代碼

複製代碼

select *
from dbo.Customers as C
 outer apply
    (select top 2 *
     from dbo.Orders as O
     where C.customerid=O.customerid
     order by orderid desc) as CA

複製代碼

複製代碼

結果如圖:

結果分析:

  發現outer apply得到的結果比cross多了一行,我們結合上面所寫的區別(cross apply和outer apply 總是包含步驟A1,只有outer apply包含步驟A2,如果cross apply左行應用右表表達式時返回空積,則不返回該行。而outer apply返回改行,並且改行的右表表達式的屬性爲null)就會知道了。

 

 

回到目錄

Sql學習第四天——SQL 關於with cube ,with rollup 和 grouping

關於with cube ,with rollup 和 grouping

通過查看sql 2005的幫助文檔找到了CUBE 和 ROLLUP 之間的具體區別

  1. CUBE 生成的結果集顯示了所選列中值的所有組合的聚合。
  2. ROLLUP 生成的結果集顯示了所選列中值的某一層次結構的聚合。

再看看對grouping的解釋:

  當行由 CUBE 或 ROLLUP 運算符添加時,該函數將導致附加列的輸出值爲 1;當行不由 CUBE 或 ROLLUP 運算符添加時,該函數將導致附加列的輸出值爲 0。

僅在與包含 CUBE 或 ROLLUP 運算符的 GROUP BY 子句相關聯的選擇列表中才允許分組。

當看到以上的解釋肯定非常的模糊,不知所云和不知道該怎樣用,下面通過實例操作來體驗一下:

先建表(dbo.PeopleInfo):

複製代碼

複製代碼

CREATE TABLE [dbo].[PeopleInfo](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [name] [nchar](10) COLLATE Chinese_PRC_CI_AS NULL,
    [numb] [nchar](10) COLLATE Chinese_PRC_CI_AS NOT NULL,
    [phone] [nchar](10) COLLATE Chinese_PRC_CI_AS NULL,
    [FenShu] [int] NULL
) ON [PRIMARY]

複製代碼

複製代碼

向表插入數據:

複製代碼

insert into peopleinfo([name],numb,phone,fenshu) values ('李歡','3223','1365255',80)
insert into peopleinfo([name],numb,phone,fenshu) values ('李歡','322123','1',90)
insert into peopleinfo([name],numb,phone,fenshu) values ('李名','3213112352','13152',56)
insert into peopleinfo([name],numb,phone,fenshu) values ('李名','32132312','13342563',60)
insert into peopleinfo([name],numb,phone,fenshu) values ('王華','3223','1365255',80)

複製代碼

查詢出插入的全部數據:

select * from dbo.PeopleInfo

結果如圖:

操作一:先試試:1, 查詢所有數據;2,用group by 查詢所有數據;3,用with cube。這三種情況的比較

SQL語句如下:

複製代碼

select * from dbo.PeopleInfo                                                        --1, 查詢所有數據;

select [name],numb,sum(fenshu) from dbo.PeopleInfo group by [name],numb             --2,用group by 查詢所有數據;

select [name],numb,sum(fenshu) from dbo.PeopleInfo group by [name],numb with cube   --3,用with cube。這三種情況的比較

複製代碼

結果如圖:

結果分析:

  用第三種(用with cube)爲什麼會多出來有null的字段值呢?通過分析圖上的值得組合會發現是怎麼回事兒了,以第三條數據(李歡,null,170)爲例:它只是把姓名是【李歡】的分爲了一組,而沒有考慮【numb】,所以有多出來了第三條數據,也說明了170是怎麼來的。其他的也是這樣。再回顧一下幫助文檔的解釋:CUBE 生成的結果集顯示了所選列中值的所有組合的聚合, 發現明瞭了許多。

操作二:1,用with cube;2,用with rollup 這兩種情況的比較

SQL語句如下:

select [name],numb,sum(fenshu) from dbo.PeopleInfo group by [name],numb with cube    --用with cube。

select [name],numb,sum(fenshu) from dbo.PeopleInfo group by [name],numb with rollup  --用with rollup。

結果如圖:

結果分析:

  爲什麼with cube 比 with rollup多出來一部分呢?原來它沒有顯示,以【numb】分組而不考慮【name】的數據情況。再回顧一下幫助文檔的解釋:ROLLUP 生成的結果集顯示了所選列中值的某一層次結構的聚合,那這個【某一層次】又是以什麼爲標準的呢?我的猜想是:距離group up最近的字段必須考慮在分組內。

證明猜想實例:

操作:用兩個group up 交換字段位置的sql語句和一個在group up 後面增加一個字段的sql語句進行比較:

SQL語句如下:

 

複製代碼

select [name],numb from dbo.PeopleInfo group by [name],numb with rollup

select [name],numb from dbo.PeopleInfo group by numb,[name] with rollup

select [name],numb,phone from dbo.PeopleInfo group by [name],numb,phone with rollup

複製代碼

 

結果如圖:

通過結果圖的比較發現猜想是正確的。

---------------------------------------------------grouping-------------------------------------------------

現在來看看grouping的實例:

SQL語句看看與with rollup的結合(與with cube的結合是一樣的):

select [name],numb,grouping(numb) from dbo.PeopleInfo group by [name],numb with rollup

結果如圖:

結果分析:

  結合幫助文檔的解釋:當行由 CUBE 或 ROLLUP 運算符添加時,該函數將導致附加列的輸出值爲 1;當行不由 CUBE 或 ROLLUP 運算符添加時,該函數將導致附加列的輸出值爲 0。  很容易理解再此就不多解釋了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章