理解T-SQL:高级查询
1. 子查詢
? 子查詢是嵌套在其它查詢中常規(guī)的SQL查詢,當(dāng)需要一個(gè)Select語(yǔ)句作為數(shù)據(jù)部分的基礎(chǔ)或另一個(gè)查詢中的條件的要素時(shí),就是創(chuàng)建子查詢
? 子查詢經(jīng)常滿足下列幾種需求:
?? a. 把一個(gè)查詢分解成一系列的邏輯步驟
?? b. 提供一個(gè)列表作為where子句和[IN|EXSITS|ANY|ALL]的目標(biāo)對(duì)象
?? c. 提供由父查詢中每一條記錄驅(qū)動(dòng)的查找
? 值得注意的是:大部分子查詢可以用聯(lián)結(jié)來(lái)表示,在可以使用聯(lián)結(jié)替代子查詢的地方 ,聯(lián)結(jié)通常是更可取的選擇。
● 嵌套子查詢[nested subquery]
?? 嵌套子查詢只朝一個(gè)方向進(jìn)行--要么返回一個(gè)用于外部查詢的值,要么返回一個(gè)與IN運(yùn)算符一起使用的值的列表。
?? 用"="運(yùn)算符時(shí),返回一個(gè)值的查詢(從一行返回一列), 用"in"運(yùn)算符時(shí),返回一個(gè)列表.
?? 語(yǔ)法:? Select <Columns> from <Table> where <OneColumn>=(Select <OneColumn> from <OtherTable> where <只返回一行的條件>)
??????????? Select <Columns> from <Table> where <OneColumn> IN (Select <OneColumn> from <OtherTable> where <條件>)
?? 舉例1: 使用單值Select語(yǔ)句的嵌套查詢
????? 假設(shè)有兩張表:Orders , OrderDetails.
?????? Orders表中有以下字段:[OrderID],[EmployeeID],[OrderDate],[shippedDate]..
?????? OrderDetails表中有以下字段: [OrderID],[ProductID],[UnitPrice]..
?????? 現(xiàn)在需要找到OrderDetails表中最早日期的那些訂單詳細(xì)情況.按照一般情況,可以這樣做:
????????? declare @firstDatetime? smallDatetime;
????????? select @firstDatetime=min(OrderDate) from Orders;?? --@fistDatetime是返回的一個(gè)值.
????????? select * from Orders join OrderDetails on Orders.OrderID=OrderDetails.OrderID where OrderDate=@firstDatetime;
????? 但是,有了查詢子句,以上三句話可以合并成一句SQL語(yǔ)句實(shí)現(xiàn):
????????? select * from Orders join OrderDetails on Orders.OrderID=OrderDetails.OrderID where OrderDate=(select min(OrderDate) from Orders);
?? 舉例2: 使用返回多個(gè)值的子查詢的嵌套查詢
?????? 假設(shè)有兩張表:Employees , Contact
?????? Employees包括了以下字段:[EmployeeID],[ConactID], [LogInID],[Title] 用來(lái)表示雇員的信息
?????? Contact包括了以下[ConactID],[FirstName],[LastName]表示人員信息
?????? 假設(shè)想得到所有職位為Network Manager的人員的名稱,除了可以用聯(lián)結(jié)表示外,也可以用子查詢:
??????? select * from HumanResources.Employee E join Person.Contact C on E.ContactID = C.ContactID where E.Title in (select Title from HumanResources.Employee where Title='Network Manager')?
??????? 當(dāng)然,以上只是演示技巧,實(shí)際的實(shí)現(xiàn)用聯(lián)結(jié)來(lái)完成比較好:
??????? select * from HumanResources.Employee E join Person.Contact C on E.ContactID = C.ContactID where E.Title='Network Manager'
????? 除了使用IN,還匹配符合的記錄,還可以使用NOT IN來(lái)排除符合的記錄:
???????? select * from HumanResources.Employee E join Person.Contact C on E.ContactID = C.ContactID where E.Title NOT IN (select Title from HumanResources.Employee where Title='Network Manager')
?
● ANY,SOME,ALL運(yùn)算符
??? IN和=運(yùn)算符都是完全匹配記錄的,假設(shè)想要做的是不是完全匹配,就可以使用ANY,SOME,ALL運(yùn)算符
??? ANY和SOME功能等同,允許在子查詢創(chuàng)建的列表上使用范圍更廣的其它運(yùn)算符,如>=,<=,<>,!…
??? 以>為例,>SOME(<列表項(xiàng)>),意味值大于值中的任何一個(gè),即大于一個(gè)最小值,因此>SOME(1,2,3)意味著大于1,如果與=使用,則與IN運(yùn)算符功能相同
??? 如果是>ALL(1,2,3),則意味著大于其中的所有值,即大于最大值.
?
2.相關(guān)子查詢
??? 相關(guān)子查詢是那些能夠變不可能為可能的事物之一,此外,它經(jīng)常能把幾行代碼變成一行,并且常常帶來(lái)性能提升.相關(guān)子查詢需要有別于常規(guī)的徹底不同的思維方式.
??? 相關(guān)子查詢與嵌套子查詢不同之處在于:嵌套子查詢中,內(nèi)部查詢處理一次,信息被傳出用于外部查詢.外部的查詢也只執(zhí)行一次. 而相關(guān)子查詢中,信息是雙向進(jìn)行的.內(nèi)部查詢根據(jù)外部查詢提供的信息執(zhí)行,反之亦然.
??? 相關(guān)子查詢執(zhí)行的三個(gè)步驟:
?????? a. 外部查詢得到一條記錄并傳入到內(nèi)部查詢
?????? b. 內(nèi)部查詢基于傳入的值執(zhí)行
?????? c. 內(nèi)部查詢從其結(jié)果中把值傳回到外部查詢
? 舉例: 現(xiàn)有一張Orders表,有以下字段:
OrderID???? CustomerID??? OrderDate????????????????????????????? Freight
----------- ----------???? -----------------------????????? ---------------------
10248?????? VINET????? 1996-07-04 00:00:00.000???????????? 32.38
10249?????? TOMSP????? 1996-07-05 00:00:00.000?????????? 11.61
10250?????? HANAR????? 1996-07-08 00:00:00.000?????????? 65.83
10251?????? VICTE????? 1996-07-08 00:00:00.000??????????? 41.34
10252?????? SUPRD????? 1996-07-09 00:00:00.000?????????? 51.30
10253?????? HANAR????? 1996-07-10 00:00:00.000?????????? 58.17
10254?????? CHOPS????? 1996-07-11 00:00:00.000?????????? 22.98
10255?????? RICSU????? 1996-07-12 00:00:00.000??????????? 148.33
10256?????? WELLI????? 1996-07-15 00:00:00.000??????????? 13.97
10257?????? HILAA????? 1996-07-16 00:00:00.000??????????? 81.91
10258?????? ERNSH????? 1996-07-17 00:00:00.000?????????? 140.51
10259?????? CENTC????? 1996-07-18 00:00:00.000?????????? 3.25
...
??? 字段分別表示訂單號(hào)/客戶ID/訂購(gòu)日期/運(yùn)費(fèi)
??? 現(xiàn)在我想要知道每個(gè)顧客最早一次訂單的OrderID信息.
??? 如果按照我們的想法,找出所有記錄中最早訂單是這樣子的語(yǔ)句:
????????? select min(orderDate) from Orders;? -->是所有訂單中最早的訂單日期,是一個(gè)值
??? 然后,找出每個(gè)顧客的最早訂單信息:
????????? select customerID,min(orderDate) from Orders group by customerID;? --以上,Group by語(yǔ)句不能少.是按組進(jìn)行歸納,得出每個(gè)顧客最早的訂單日期
??? 但是,想知道每個(gè)顧客最早訂單日期的訂單號(hào),就沒(méi)有辦法了.使用以下語(yǔ)句是不行的:
????????? select OrderID,customerID,min(orderDate) from Orders group by customerID; --OrderID不能被customerID進(jìn)行歸納分組
??? 所以,解決辦法可以使用一個(gè)臨時(shí)表(#MinORderDates),然后分為兩個(gè)SQL語(yǔ)句,如下:
????????? select customerID,min(OrderDate) as OrderDate into #MinOrderDates from Orders group by customerID;
???????? select O.OrderID,O.customerID,O.OrderDate from Orders O join #MinOrderDates M on O.customerID = M.customerID and O.OrderDate=M.OrderDate
???? 那么,是用相關(guān)子查詢?cè)撛趺唇鉀Q呢?
??????? select o1.customerID,o1.OrderID,o1.OrderDate from Orders o1 where o1.orderDate=(select min(o2.orderDate) from Orders o2 where o2.customerID=o1.customerID)
???? 注意以上語(yǔ)句,子查詢中where子句會(huì)引用外部查詢的表字段.所以,指定別名是必需的.
?
3. SELECT列表子查詢
?? 子查詢也能用來(lái)在選擇結(jié)果中提供一種不同類型的答案,這些情形通常出現(xiàn)在要找尋的信息與查詢中的其它數(shù)據(jù)全然不同的時(shí)候,(例如,想要在一個(gè)字段上進(jìn)行聚集,卻不希望因此而影響返回的其它字段)
?? 還是像上一節(jié)的查詢一樣,不過(guò)這次需要獲得customer的LastName,而不是customerID
??? select c.LastName? (select MIN(OrderDate) from Orders o where o.customerID=c.customerID) as “OrderDate” from Customers c
總結(jié)
以上是生活随笔為你收集整理的理解T-SQL:高级查询的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Flex中你最应该知道的10点
- 下一篇: SQL数据类型详解