理解T-SQL:高级查询
1. 子查詢
? 子查詢是嵌套在其它查詢中常規的SQL查詢,當需要一個Select語句作為數據部分的基礎或另一個查詢中的條件的要素時,就是創建子查詢
? 子查詢經常滿足下列幾種需求:
?? a. 把一個查詢分解成一系列的邏輯步驟
?? b. 提供一個列表作為where子句和[IN|EXSITS|ANY|ALL]的目標對象
?? c. 提供由父查詢中每一條記錄驅動的查找
? 值得注意的是:大部分子查詢可以用聯結來表示,在可以使用聯結替代子查詢的地方 ,聯結通常是更可取的選擇。
● 嵌套子查詢[nested subquery]
?? 嵌套子查詢只朝一個方向進行--要么返回一個用于外部查詢的值,要么返回一個與IN運算符一起使用的值的列表。
?? 用"="運算符時,返回一個值的查詢(從一行返回一列), 用"in"運算符時,返回一個列表.
?? 語法:? 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語句的嵌套查詢
????? 假設有兩張表:Orders , OrderDetails.
?????? Orders表中有以下字段:[OrderID],[EmployeeID],[OrderDate],[shippedDate]..
?????? OrderDetails表中有以下字段: [OrderID],[ProductID],[UnitPrice]..
?????? 現在需要找到OrderDetails表中最早日期的那些訂單詳細情況.按照一般情況,可以這樣做:
????????? declare @firstDatetime? smallDatetime;
????????? select @firstDatetime=min(OrderDate) from Orders;?? --@fistDatetime是返回的一個值.
????????? select * from Orders join OrderDetails on Orders.OrderID=OrderDetails.OrderID where OrderDate=@firstDatetime;
????? 但是,有了查詢子句,以上三句話可以合并成一句SQL語句實現:
????????? select * from Orders join OrderDetails on Orders.OrderID=OrderDetails.OrderID where OrderDate=(select min(OrderDate) from Orders);
?? 舉例2: 使用返回多個值的子查詢的嵌套查詢
?????? 假設有兩張表:Employees , Contact
?????? Employees包括了以下字段:[EmployeeID],[ConactID], [LogInID],[Title] 用來表示雇員的信息
?????? Contact包括了以下[ConactID],[FirstName],[LastName]表示人員信息
?????? 假設想得到所有職位為Network Manager的人員的名稱,除了可以用聯結表示外,也可以用子查詢:
??????? 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')?
??????? 當然,以上只是演示技巧,實際的實現用聯結來完成比較好:
??????? select * from HumanResources.Employee E join Person.Contact C on E.ContactID = C.ContactID where E.Title='Network Manager'
????? 除了使用IN,還匹配符合的記錄,還可以使用NOT IN來排除符合的記錄:
???????? 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運算符
??? IN和=運算符都是完全匹配記錄的,假設想要做的是不是完全匹配,就可以使用ANY,SOME,ALL運算符
??? ANY和SOME功能等同,允許在子查詢創建的列表上使用范圍更廣的其它運算符,如>=,<=,<>,!…
??? 以>為例,>SOME(<列表項>),意味值大于值中的任何一個,即大于一個最小值,因此>SOME(1,2,3)意味著大于1,如果與=使用,則與IN運算符功能相同
??? 如果是>ALL(1,2,3),則意味著大于其中的所有值,即大于最大值.
?
2.相關子查詢
??? 相關子查詢是那些能夠變不可能為可能的事物之一,此外,它經常能把幾行代碼變成一行,并且常常帶來性能提升.相關子查詢需要有別于常規的徹底不同的思維方式.
??? 相關子查詢與嵌套子查詢不同之處在于:嵌套子查詢中,內部查詢處理一次,信息被傳出用于外部查詢.外部的查詢也只執行一次. 而相關子查詢中,信息是雙向進行的.內部查詢根據外部查詢提供的信息執行,反之亦然.
??? 相關子查詢執行的三個步驟:
?????? a. 外部查詢得到一條記錄并傳入到內部查詢
?????? b. 內部查詢基于傳入的值執行
?????? c. 內部查詢從其結果中把值傳回到外部查詢
? 舉例: 現有一張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
...
??? 字段分別表示訂單號/客戶ID/訂購日期/運費
??? 現在我想要知道每個顧客最早一次訂單的OrderID信息.
??? 如果按照我們的想法,找出所有記錄中最早訂單是這樣子的語句:
????????? select min(orderDate) from Orders;? -->是所有訂單中最早的訂單日期,是一個值
??? 然后,找出每個顧客的最早訂單信息:
????????? select customerID,min(orderDate) from Orders group by customerID;? --以上,Group by語句不能少.是按組進行歸納,得出每個顧客最早的訂單日期
??? 但是,想知道每個顧客最早訂單日期的訂單號,就沒有辦法了.使用以下語句是不行的:
????????? select OrderID,customerID,min(orderDate) from Orders group by customerID; --OrderID不能被customerID進行歸納分組
??? 所以,解決辦法可以使用一個臨時表(#MinORderDates),然后分為兩個SQL語句,如下:
????????? 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
???? 那么,是用相關子查詢該怎么解決呢?
??????? 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)
???? 注意以上語句,子查詢中where子句會引用外部查詢的表字段.所以,指定別名是必需的.
?
3. SELECT列表子查詢
?? 子查詢也能用來在選擇結果中提供一種不同類型的答案,這些情形通常出現在要找尋的信息與查詢中的其它數據全然不同的時候,(例如,想要在一個字段上進行聚集,卻不希望因此而影響返回的其它字段)
?? 還是像上一節的查詢一樣,不過這次需要獲得customer的LastName,而不是customerID
??? select c.LastName? (select MIN(OrderDate) from Orders o where o.customerID=c.customerID) as “OrderDate” from Customers c
總結
以上是生活随笔為你收集整理的理解T-SQL:高级查询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Flex中你最应该知道的10点
- 下一篇: Microsoft Office Bac