sql語法相關子查詢與非相關子查詢

流浪的野狼發表於2013-10-05
sql語法相關子查詢與非相關子查詢
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 rderDate=
(
    selectMax(OrderDate)From Orders As o2 where o2.EmployeeId=o1.EmployeeId--得到每名員工的最近訂單日期
)
and rderId=
(
 
    selectMax(OrderId)From Orders As o2 Where o2.EmployeeId=o1.EmployeeId and o2.OrderDate=o1.OrderDate--得到每名員工每個訂單日期的最大OrderId
)
轉自:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28612416/viewspace-773763/,如需轉載,請註明出處,否則將追究法律責任。

相關文章