子查詢

1:標量子查詢(相對於多值子查詢):

只有標量子查詢返回的是單個記錄或者不返回,就是有效的子查詢。

Ex1:select OrderId From Orders where EmployeeId=

(select EmployeeId From employees where lastName like N'Davolio')

將’Davolio’改爲'D%'時,這個時候子查詢中返回結果爲2行,等號右邊此時爲多值,查詢失敗.將’=’改爲in謂詞.查詢才能通過.

employees表中無lastname=’jason’,外部查詢將返回null.

 

2:非相關子查詢(嵌套子查詢)

 

一個select...From...Where查詢語句塊可以嵌套在另一個select...From...Where查詢塊的Where子句
中,稱爲嵌套查詢。外層查詢稱爲父查詢,主查詢。內層查詢稱爲子查詢,從查詢。
子查詢可以嵌套多層,子查詢查詢到的結果又成爲父查詢的條件。子查詢中不能有order by分組語句。
先處理子查詢,再處理父查詢。 
細分如下:

1。 簡單嵌套查詢 
     查詢選修課程號爲'101'並且成績高於學生號爲'9501101'的所有學生的成績.
select * from sclass 
where cno='101' and degree>=
(select degree from sclass where sno='9501101'and cno='101')  

當子查詢跟隨在 =!=<<=>>= 之後, 子查詢的返回值只能是一個, 否則應在外層where子句中用
一個in限定符,即要返回多個值,要用in或者not in

2。 帶[not] in的嵌套查詢 
     只要主查詢中列或運算式是在(不在)子查詢所得結果列表中的話,則主查詢的結果爲我們要的數據
    select sales_id,tot_amt
    from sales 
    where sale _id  in(select sale_id from employee where sex='F')
where sno not in(Select distinct sno from sclass)

 


3。 帶exists的嵌套查詢
 子查詢的結果至少存在一條數據時,則主查詢的結果爲我們要的數據。(exists)或自查詢的結果找不到數據時,則主查詢的結果爲我們要的數據(not exists)
 我們經常查詢的兩個表有多少重複的記錄就用這個
 以下範例讓你找出滯銷的產品,也就是尚未有任何銷售記錄的庫存產品。此範例主要是查詢以庫文件中的每一條產品代碼到銷售明細表中去查詢,如果查詢不到任何一條,表示該產品未曾賣出任何一件。
  select * from stock a
  where not exists(select * from sale_item b
                          where a.prod_id=b.prod_id and a.stup_id=b.stup_id)

 4.select ... where 列或運算式 比較運算運算【any|all](子查詢)


   只要主查詢中列或運算式與子查詢所得結果中任一(any)或全部(all)數據符合比較條件的話則主查詢的結果爲我們要的數據

  select sale_id,tot_amt
    from sales 
    where tot_amt>any(select tot_amt from sales where sale_id='e0013'and 'order_date='1996/11/10')

       選出不同的人金額最高的訂單
    select *  from  sales a
    where tomat=(select max(totmat) from sales  where name=a.name)

 

 

3:相關子查詢(多值子查詢)

1>非相關子查詢是獨立於外部查詢的子查詢,子查詢總共執行一次,執行完畢後將值傳遞給外部查詢。 
2>相關子查詢的執行依賴於外部查詢的數據,外部查詢執行一行,子查詢就執行一次。

  查詢中再查詢,通常是以一個查詢作爲條件來供另一個查詢使用
      例:有work表和部門表
         A:檢索出在部門表中登記的所有部門的職工基本資料
           select * from work where 部門編號 in [not in](select 部門編號 from dbo.部門) 
         B:檢索出在work表中每一個部門的最高基本工資的職工資料
           select * from work a where 基本工資=(select max(基本工資) from work b where a.部門名稱=b.部門名稱) 
           說明:由外查詢提供一個部門名稱給內查詢,內查詢利用這個部門名稱找到該部門的最高基本工資,然後外查詢根據基本工資判斷是否等於最高工資,如果是的,則顯示出來.
           相當於:select * from work,(select 部門名稱,max(基本工資) as 基本工資 from work group by 部門名稱 as t) where work.基本工資=t.基本工資 and work.部門名稱=t.部門名稱
         C:用嵌套work表和嵌套部門表,在嵌套work表中檢索出姓名和職工號都在嵌套部門存在的職工資料 
           select * from 嵌套work where 職工號 in (select 職工號 from 嵌套部門) and 姓名 in (select 姓名 from 嵌套部門) [察看結果,分析原因] (錯誤,因爲這兩個in不是一對一
           改:select * from 嵌套work a,嵌套部門 b where a.職工號=b.職工號 and a.姓名=b.姓名 
           改:select * from 嵌套work where 職工號=(select 職工號 from 嵌套部門) and 姓名=(select 姓名 from 嵌套部門) [行嗎?爲什麼,分析原因?] 不能後面的select得到的結果不是一個值而又跟在=後必然出錯

在嵌套中使用exists關鍵字[存在]
例:1:用嵌套work表和嵌套部門表,在嵌套work表中檢索出姓名和職工號都在嵌套部門存在的職工資料 
     select * from 嵌套work a where exists (select * from 嵌套部門 b where a.姓名=b.姓名 and a.職工號=b.職工號)
   2:在work表檢索出在部門表沒有的職工
     select * from work where not exists (select * from 部門 where 部門.部門編號=work.部門編號)
     能否改成:select * from work where exists (select * from 部門 where 部門.部門編號<>work.部門編號) 是不能的,

在列清單中使用select
例:1:在work1表和部門表中檢索出所有部門的部門名稱和基本工資總和
    select 部門名稱,(select sum(基本工資) from work1 b where a.部門編號=b.部門編號) from 部門 a
   2:檢索各部門的職工人數
    select 部門編號,部門名稱,(select count(職工號) from work1 a where a.部門編號=b.部門編號) as 人數 from 部門 b
   3:在商品表和銷售表中查詢每一職工的姓名,所屬部門,銷售總量                   
    select 姓名,所屬部門,(select sum(銷售量) from 商品銷售 a where a.職工號=b.職工號) as 銷售總量 from 嵌套部門 b

說明:都是相關子查詢的特殊情況,外層的查詢是內層查詢的條件如:a.職工號=b.職工號,內層條件成立則得到的些行記錄是併入外層查詢的最終結果,否則不記錄入最後結果

許多查詢都可以通過執行一次子查詢並將得到的值代入外部查詢的 WHERE 子句中進行計算。在包括相關子查詢(也稱爲重複子查詢)的查詢中,子查詢依靠外部查詢獲得值。這意味着子查詢是重複執行的,爲外部查詢可能選擇的每一行均執行一次。

此查詢在 SalesPerson 表中檢索獎金爲 5000 且僱員標識號與 Employee 和 SalesPerson 表中的標識號相匹配的僱員的名和姓的一個實例。

USE AdventureWorks2008R2;GOSELECT DISTINCT c.LastName, c.FirstName, e.BusinessEntityID FROM Person.Person AS c JOIN HumanResources.Employee AS eON e.BusinessEntityID = c.BusinessEntityID WHERE 5000.00 IN    (SELECT Bonus    FROM Sales.SalesPerson sp    WHERE e.BusinessEntityID = sp.BusinessEntityID) ;GO

下面是結果集:

LastName FirstName BusinessEntityID

-------------------------- ---------- ------------

Ansman-Wolfe Pamela 280

Saraiva José 282

(2 row(s) affected)

該語句中前面的子查詢無法獨立於外部查詢進行計算。它需要 Employee.BusinessEntityID 值,但是此值隨 SQL Server 檢查 Employee 中的不同行而改變。

下面準確說明了如何計算此查詢:SQL Server 通過將每一行的值代入內部查詢,考慮 Employee 表中的每一行是否都包括在結果中。例如,如果 SQL Server 首先檢查 Syed Abbas 行,那麼變量 Employee.BusinessEntityID 將取值 285,SQL Server 將該值代入內部查詢。

 USE AdventureWorks2008R2;
GO
SELECT Bonus
FROM Sales.SalesPerson
WHERE BusinessEntityID = 285;

結果爲 0(Syed Abbas 沒有收到獎金,因爲他不是銷售人員),因此外部查詢計算爲:

 
USE AdventureWorks2008R2;GOSELECT LastName, FirstNameFROM Person.Person AS c JOIN HumanResources.Employee AS eON e.BusinessEntityID = c.BusinessEntityID WHERE 5000 IN (0.00)

引用外部查詢列的子查詢。邏輯上講,子查詢會爲外部查詢的每行計算一次。

Ex4:查詢每個員工employee最近的一個訂單

思路:--需要附加屬性(Tiebreaker)Max(OrderDate)最大訂單日期和Max(OrderId)最大訂單號來確定每名員工的最近訂單狀況

select OrderId,CustomerId,EmployeeId,OrderDate From Orders As o1 where OrderDate=

(

    select Max(OrderDate) From Orders As o2 where o2.EmployeeId=o1.EmployeeId--得到每名員工的最近訂單日期

)

and OrderId=

(

    select Max(OrderId) From Orders As o2 Where o2.EmployeeId=o1.EmployeeId and o2.OrderDate=o1.OrderDate--得到每名員工每個訂單日期的最大OrderId

)

 

發佈了3 篇原創文章 · 獲贊 2 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章