相关子查询 与非相关子查询
1:標(biāo)量子查詢(相對(duì)于多值子查詢):
只有標(biāo)量子查詢返回的是單個(gè)記錄或者不返回,就是有效的子查詢。
Ex1:select OrderId From Orders where EmployeeId=
(select EmployeeId From employees where lastName like N'Davolio')
將’Davolio’改為'D%'時(shí),這個(gè)時(shí)候子查詢中返回結(jié)果為2行,等號(hào)右邊此時(shí)為多值,查詢失敗.將’=’改為in謂詞.查詢才能通過(guò).
employees表中無(wú)lastname=’jason’,外部查詢將返回null.
?
2:非相關(guān)子查詢(嵌套子查詢)
?
一個(gè)select...From...Where查詢語(yǔ)句塊可以嵌套在另一個(gè)select...From...Where查詢塊的Where子句
中,稱為嵌套查詢。外層查詢稱為父查詢,主查詢。內(nèi)層查詢稱為子查詢,從查詢。
子查詢可以嵌套多層,子查詢查詢到的結(jié)果又成為父查詢的條件。子查詢中不能有order by分組語(yǔ)句。
先處理子查詢,再處理父查詢。
細(xì)分如下:
1。 簡(jiǎn)單嵌套查詢
???? 查詢選修課程號(hào)為'101'并且成績(jī)高于學(xué)生號(hào)為'9501101'的所有學(xué)生的成績(jī).
select * from sclass
where cno='101' and degree>=
(select degree from sclass where sno='9501101'and cno='101')??
當(dāng)子查詢跟隨在 =、!=、<、<=、>、>= 之后, 子查詢的返回值只能是一個(gè), 否則應(yīng)在外層where子句中用
一個(gè)in限定符,即要返回多個(gè)值,要用in或者not in
2。 帶[not] in的嵌套查詢?
??? ?只要主查詢中列或運(yùn)算式是在(不在)子查詢所得結(jié)果列表中的話,則主查詢的結(jié)果為我們要的數(shù)據(jù)
????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的嵌套查詢
?子查詢的結(jié)果至少存在一條數(shù)據(jù)時(shí),則主查詢的結(jié)果為我們要的數(shù)據(jù)。(exists)或自查詢的結(jié)果找不到數(shù)據(jù)時(shí),則主查詢的結(jié)果為我們要的數(shù)據(jù)(not?exists)
?我們經(jīng)常查詢的兩個(gè)表有多少重復(fù)的記錄就用這個(gè)
?以下范例讓你找出滯銷(xiāo)的產(chǎn)品,也就是尚未有任何銷(xiāo)售記錄的庫(kù)存產(chǎn)品。此范例主要是查詢以庫(kù)文件中的每一條產(chǎn)品代碼到銷(xiāo)售明細(xì)表中去查詢,如果查詢不到任何一條,表示該產(chǎn)品未曾賣(mài)出任何一件。
??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?列或運(yùn)算式?比較運(yùn)算運(yùn)算【any|all](子查詢)
???只要主查詢中列或運(yùn)算式與子查詢所得結(jié)果中任一(any)或全部(all)數(shù)據(jù)符合比較條件的話則主查詢的結(jié)果為我們要的數(shù)據(jù)
??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:相關(guān)子查詢(多值子查詢)
1>非相關(guān)子查詢是獨(dú)立于外部查詢的子查詢,子查詢總共執(zhí)行一次,執(zhí)行完畢后將值傳遞給外部查詢。
2>相關(guān)子查詢的執(zhí)行依賴于外部查詢的數(shù)據(jù),外部查詢執(zhí)行一行,子查詢就執(zhí)行一次。
? 查詢中再查詢,通常是以一個(gè)查詢作為條件來(lái)供另一個(gè)查詢使用
????? 例:有work表和部門(mén)表
???????? A:檢索出在部門(mén)表中登記的所有部門(mén)的職工基本資料
?????????? select * from work where 部門(mén)編號(hào) in [not in](select 部門(mén)編號(hào) from dbo.部門(mén))
???????? B:檢索出在work表中每一個(gè)部門(mén)的最高基本工資的職工資料
?????????? select * from work a where 基本工資=(select max(基本工資) from work b where a.部門(mén)名稱=b.部門(mén)名稱)
?????????? 說(shuō)明:由外查詢提供一個(gè)部門(mén)名稱給內(nèi)查詢,內(nèi)查詢利用這個(gè)部門(mén)名稱找到該部門(mén)的最高基本工資,然后外查詢根據(jù)基本工資判斷是否等于最高工資,如果是的,則顯示出來(lái).
?????????? 相當(dāng)于:select * from work,(select 部門(mén)名稱,max(基本工資) as 基本工資 from work group by 部門(mén)名稱 as t) where work.基本工資=t.基本工資 and work.部門(mén)名稱=t.部門(mén)名稱
???????? C:用嵌套work表和嵌套部門(mén)表,在嵌套work表中檢索出姓名和職工號(hào)都在嵌套部門(mén)存在的職工資料
?????????? select * from 嵌套work where 職工號(hào) in (select 職工號(hào) from 嵌套部門(mén)) and 姓名 in (select 姓名 from 嵌套部門(mén)) [察看結(jié)果,分析原因] (錯(cuò)誤,因?yàn)檫@兩個(gè)in不是一對(duì)一
?????????? 改:select * from 嵌套work a,嵌套部門(mén) b where a.職工號(hào)=b.職工號(hào) and a.姓名=b.姓名
?????????? 改:select * from 嵌套work where 職工號(hào)=(select 職工號(hào) from 嵌套部門(mén)) and 姓名=(select 姓名 from 嵌套部門(mén)) [行嗎?為什么,分析原因?] 不能后面的select得到的結(jié)果不是一個(gè)值而又跟在=后必然出錯(cuò)
在嵌套中使用exists關(guān)鍵字[存在]
例:1:用嵌套work表和嵌套部門(mén)表,在嵌套work表中檢索出姓名和職工號(hào)都在嵌套部門(mén)存在的職工資料
???? select * from 嵌套work a where exists (select * from 嵌套部門(mén) b where a.姓名=b.姓名 and a.職工號(hào)=b.職工號(hào))
?? 2:在work表檢索出在部門(mén)表沒(méi)有的職工
???? select * from work where not exists (select * from 部門(mén) where 部門(mén).部門(mén)編號(hào)=work.部門(mén)編號(hào))
???? 能否改成:select * from work where exists (select * from 部門(mén) where 部門(mén).部門(mén)編號(hào)<>work.部門(mén)編號(hào)) 是不能的,
在列清單中使用select
例:1:在work1表和部門(mén)表中檢索出所有部門(mén)的部門(mén)名稱和基本工資總和
??? select 部門(mén)名稱,(select sum(基本工資) from work1 b where a.部門(mén)編號(hào)=b.部門(mén)編號(hào)) from 部門(mén) a
?? 2:檢索各部門(mén)的職工人數(shù)
??? select 部門(mén)編號(hào),部門(mén)名稱,(select count(職工號(hào)) from work1 a where a.部門(mén)編號(hào)=b.部門(mén)編號(hào)) as 人數(shù) from 部門(mén) b
?? 3:在商品表和銷(xiāo)售表中查詢每一職工的姓名,所屬部門(mén),銷(xiāo)售總量??????????????????
??? select 姓名,所屬部門(mén),(select sum(銷(xiāo)售量) from 商品銷(xiāo)售 a where a.職工號(hào)=b.職工號(hào)) as 銷(xiāo)售總量 from 嵌套部門(mén) b
說(shuō)明:都是相關(guān)子查詢的特殊情況,外層的查詢是內(nèi)層查詢的條件如:a.職工號(hào)=b.職工號(hào),內(nèi)層條件成立則得到的些行記錄是并入外層查詢的最終結(jié)果,否則不記錄入最后結(jié)果
許多查詢都可以通過(guò)執(zhí)行一次子查詢并將得到的值代入外部查詢的 WHERE 子句中進(jìn)行計(jì)算。在包括相關(guān)子查詢(也稱為重復(fù)子查詢)的查詢中,子查詢依靠外部查詢獲得值。這意味著子查詢是重復(fù)執(zhí)行的,為外部查詢可能選擇的每一行均執(zhí)行一次。
此查詢?cè)?SalesPerson 表中檢索獎(jiǎng)金為 5000 且雇員標(biāo)識(shí)號(hào)與 Employee 和 SalesPerson 表中的標(biāo)識(shí)號(hào)相匹配的雇員的名和姓的一個(gè)實(shí)例。
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下面是結(jié)果集:
LastName FirstName BusinessEntityID
-------------------------- ---------- ------------
Ansman-Wolfe Pamela 280
Saraiva José 282
(2 row(s) affected)
該語(yǔ)句中前面的子查詢無(wú)法獨(dú)立于外部查詢進(jìn)行計(jì)算。它需要 Employee.BusinessEntityID 值,但是此值隨 SQL Server 檢查 Employee 中的不同行而改變。
下面準(zhǔn)確說(shuō)明了如何計(jì)算此查詢:SQL Server 通過(guò)將每一行的值代入內(nèi)部查詢,考慮 Employee 表中的每一行是否都包括在結(jié)果中。例如,如果 SQL Server 首先檢查 Syed Abbas 行,那么變量 Employee.BusinessEntityID 將取值 285,SQL Server 將該值代入內(nèi)部查詢。
USE AdventureWorks2008R2;GO
SELECT Bonus
FROM Sales.SalesPerson
WHERE BusinessEntityID = 285;
結(jié)果為 0(Syed Abbas 沒(méi)有收到獎(jiǎng)金,因?yàn)樗皇卿N(xiāo)售人員),因此外部查詢計(jì)算為:
USE AdventureWorks2008R2;GOSELECT LastName, FirstNameFROM Person.Person AS c JOIN HumanResources.Employee AS eON e.BusinessEntityID = c.BusinessEntityID WHERE 5000 IN (0.00)引用外部查詢列的子查詢。邏輯上講,子查詢會(huì)為外部查詢的每行計(jì)算一次。
Ex4:查詢每個(gè)員工employee最近的一個(gè)訂單
思路:--需要附加屬性(Tiebreaker)Max(OrderDate)最大訂單日期和Max(OrderId)最大訂單號(hào)來(lái)確定每名員工的最近訂單狀況
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--得到每名員工每個(gè)訂單日期的最大OrderId
)
轉(zhuǎn)載于:https://www.cnblogs.com/mjsn/p/6150810.html
總結(jié)
以上是生活随笔為你收集整理的相关子查询 与非相关子查询的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: CoreData和SQLite多线程访问
- 下一篇: Oracle数据库中有关记录个数的查询