自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

T-SQL查詢進階之深入理解子查詢

數(shù)據(jù)庫 SQL Server
本文深入解釋了T-SQL子查詢的一些重點知識,并通過實例對介紹的子查詢方法進行驗證,相信會對您有所幫助。

子查詢本質(zhì)上是嵌套進其他SELECT,UPDATE,INSERT,DELETE語句的一個被限制的SELECT語句,在子查詢中,只有下面幾個子句可以使用:SELECT子句(必須)、FROM子句(必選)、 WHERE子句(可選)  、GROUP BY(可選) 、HAVING(可選) 和ORDER BY(只有在TOP關(guān)鍵字被使用時才可用)。

子查詢也可以嵌套在其他子查詢中,這個嵌套最多可達32層。子查詢也叫內(nèi)部查詢(Inner query)或者內(nèi)部選擇(Inner Select),而包含子查詢的查詢語句也叫做外部查詢(Outter)或者外部選擇(Outer Select),子查詢的概念可以簡單用下圖闡述:

T-SQL查詢進階之深入理解子查詢

T-SQL查詢進階之深入理解子查詢

http://wiki.lessthandot.com/index.php/Subquery_typo_with_using_in。這篇文章的觀點是永遠不要再用IN和NOT IN關(guān)鍵字,我的觀點是存在即合理,我認為只有在IN里面是固定值的時候才可以用IN和NOT IN,比如:

T-SQL查詢進階之深入理解子查詢

上圖是作為數(shù)據(jù)源使用的一個子查詢。

通常來講,子查詢按照子查詢所返回數(shù)據(jù)的類型,可以分為三種,分別為:

返回一張數(shù)據(jù)表(Table)

返回一列值(Column)

返回單個值(Scalar)

下面,我們按照這三種方式來闡述子查詢

子查詢作為數(shù)據(jù)源使用

當子查詢在外部查詢的FROM子句之后使用時,子查詢被當作一個數(shù)據(jù)源使用,即使這時子查詢只返回一個單一值(Scalar)或是一列值(Column),在這里依然可以看作一個特殊的數(shù)據(jù)源,即一個二維數(shù)據(jù)表(Table).作為數(shù)據(jù)源使用的子查詢很像一個View(視圖),只是這個子查詢只是臨時存在,并不包含在數(shù)據(jù)庫中。

比如這個語句:

  1. SELECT P.ProductID, P.Name, P.ProductNumber, M.Name  
  2.  
  3. AS ProductModelName  
  4.  
  5. FROM Production.Product AS P  
  6.  
  7. INNER JOIN  
  8.  
  9. (  
  10.  
  11. SELECT Name, ProductModelID  
  12.  
  13. FROM Production.ProductModel)  
  14.  
  15. AS M  
  16.  
  17. ON P.ProductModelID = M.ProductModelID 

上述子查詢語句將ProductModel表中的子集M,作為數(shù)據(jù)源(表)和Product表進行內(nèi)連接。結(jié)果如下:

作為數(shù)據(jù)源使用也是子查詢最簡單的應用。當然,當子查詢作為數(shù)據(jù)源使用時,也分為相關(guān)子查詢和無關(guān)子查詢,這會在文章后面介紹到.

子查詢作為選擇條件使用

作為選擇條件的子查詢也是子查詢相對最復雜的應用.

作為選擇條件的子查詢是那些只返回一列(Column)的子查詢,如果作為選擇條件使用,即使只返回單個值,也可以看作是只有一行的一列.比如,在AdventureWorks中:我想取得總共請病假天數(shù)大于68小時的員工:

  1. SELECT [FirstName]  
  2.  
  3. ,[MiddleName]  
  4.  
  5. ,[LastName]  
  6.  
  7. FROM [AdventureWorks].[Person].[Contact]  
  8.  
  9. WHERE ContactID IN  
  10.  
  11. (SELECT EmployeeID  
  12.  
  13. FROM [AdventureWorks].[HumanResources].[Employee]  
  14.  
  15. WHERE SickLeaveHours>68) 

結(jié)果如下:

T-SQL查詢進階之深入理解子查詢

上面的查詢中,在IN關(guān)鍵字后面的子查詢返回一列值作為外部查詢的選擇條件使用。

同樣的,與IN關(guān)鍵字的邏輯取反的NOT IN關(guān)鍵字,這里就不再闡述了。

但是要強調(diào)的是,不要用IN和NOT IN關(guān)鍵字,這會引起很多潛在的問題,這篇文章對這個問題有著很好的闡述:

  1. SELECT [FirstName]  
  2.  
  3. ,[MiddleName]  
  4.  
  5. ,[LastName]  
  6.  
  7. FROM [AdventureWorks].[Person].[Contact]  
  8.  
  9. WHERE ContactID IN (25,33) 

只有在上面這種情況下,使用IN和NOT IN關(guān)鍵字才是安全的,其他情況下,最好使用EXISTS,NOT EXISTS,JOIN關(guān)鍵字來進行替代. 除了IN之外,用于選擇條件的關(guān)鍵字還有ANY和ALL,這兩個關(guān)鍵字和其字面意思一樣. 和"<",">",”="連接使用,比如上面用IN的那個子查詢:

我想取得總共請病假天數(shù)大于68小時的員工

用ANY關(guān)鍵字進行等效的查詢?yōu)椋?/p>

  1. SELECT [FirstName]  
  2.  
  3. ,[MiddleName]  
  4.  
  5. ,[LastName]  
  6.  
  7. FROM [AdventureWorks].[Person].[Contact]  
  8.  
  9. WHERE ContactID =ANY 
  10.  
  11. SELECT EmployeeID  
  12.  
  13. FROM [AdventureWorks].[HumanResources].[Employee]  
  14.  
  15. WHERE SickLeaveHours>68) 

在作為ANY和ALL關(guān)鍵字在子查詢中使用時,所實現(xiàn)的效果如下:

=ANY 和IN等價
<>ANY 和NOT IN等價
>ANY 大于最小的(>MIN)
<ANY 小于最大的(<MAX)
>ALL 大于最大的(>MAX)
<ALL 小于最小的(<MIN)
=ALL 下面說

=ALL關(guān)鍵字很少使用,這個的效果在子查詢中為如果只有一個返回值,則和“=”相等,而如果有多個返回值,結(jié)果為空。

這里要注意,SQL是一種很靈活的語言,就像子查詢所實現(xiàn)的效果可以使用JOIN來實現(xiàn)一樣(效果一樣,實現(xiàn)思路不同),ANY和ALL所實現(xiàn)的效果也完全可以使用其他方式來替代,按照上面表格所示,>ANY和>MIN完全等價,比如下面兩個查詢語句完全等價:

  1. SELECT *  
  2.  
  3. FROM AdventureWorks.HumanResources.Employee  
  4.  
  5. WHERE SickLeaveHours>ANY  
  6.  
  7. (SELECT SickLeaveHours  
  8.  
  9. FROM AdventureWorks.HumanResources.Employee  
  10.  
  11. WHERE SickLeaveHours>68)  
  12.  
  13. SELECT *  
  14.  
  15. FROM AdventureWorks.HumanResources.Employee  
  16.  
  17. WHERE SickLeaveHours> 
  18.  
  19. (SELECT MIN(SickLeaveHours)  
  20.  
  21. FROM AdventureWorks.HumanResources.Employee  
  22.  
  23. WHERE SickLeaveHours>68) 

 #p#

相關(guān)子查詢和EXISTS關(guān)鍵字

前面所說的查詢都是無關(guān)子查詢(Uncorrelated subquery),子查詢中還有一類很重要的查詢是相關(guān)子查詢(Correlated subquery),也叫重復子查詢比如,還是上面那個查詢,用相關(guān)子查詢來寫:

我想取得總共請病假天數(shù)大于68天的員工:

  1. SELECT [FirstName]  
  2.  
  3. ,[MiddleName]  
  4.  
  5. ,[LastName]  
  6.  
  7. FROM [AdventureWorks].[Person].[Contact] c  
  8.  
  9. WHERE EXISTS  
  10.  
  11. (SELECT *  
  12.  
  13. FROM [AdventureWorks].[HumanResources].[Employee] e  
  14.  
  15. WHERE c.ContactID=e.ContactID AND e.SickLeaveHours>68) 

結(jié)果和使用IN關(guān)鍵字的查詢結(jié)果相同:

T-SQL查詢進階之深入理解子查詢

如何區(qū)別相關(guān)子查詢和無關(guān)子查詢呢?最簡單的辦法就是直接看子查詢本身能否執(zhí)行,比如上面的例子中的子查詢:

  1. (SELECT *  
  2.  
  3. FROM [AdventureWorks].[HumanResources].[Employee] e  
  4.  
  5. WHERE c.ContactID=e.ContactID AND e.SickLeaveHours>68) 

這一句本身執(zhí)行本身會報錯.因為這句引用到了外部查詢的表。

對于無關(guān)子查詢來說,整個查詢的過程為子查詢只執(zhí)行一次,然后交給外部查詢,比如:

  1. SELECT *  
  2.  
  3. FROM AdventureWorks.HumanResources.Employee  
  4.  
  5. WHERE SickLeaveHours>ANY  
  6.  
  7. SQLRESULT 

上面的無關(guān)子查詢,整個查詢過程可以看作是子查詢首先返回SQLResult(SQL結(jié)果集),然后交給外部查詢使用,整個過程子查詢只執(zhí)行一次。

而相反,作為相關(guān)子查詢,子查詢的執(zhí)行的次數(shù)依賴于外部查詢,外部查詢每執(zhí)行一行,子查詢執(zhí)行一次,比如:

還是上面的例子:我想取得總共請病假天數(shù)大于68天的員工:

  1. SELECT [FirstName]  
  2.  
  3. ,[MiddleName]  
  4.  
  5. ,[LastName]  
  6.  
  7. FROM [AdventureWorks].[Person].[Contact] c  
  8.  
  9. WHERE EXISTS  
  10.  
  11. (SELECT *  
  12.  
  13. FROM [AdventureWorks].[HumanResources].[Employee] e  
  14.  
  15. WHERE c.ContactID=e.ContactID AND e.SickLeaveHours>68) 

step 1:

  1. SELECT [FirstName]  
  2.  
  3. ,[MiddleName]  
  4.  
  5. ,[LastName]  
  6.  
  7. FROM [AdventureWorks].[Person].[Contact] c  
  8.  
  9. WHERE EXISTS  
  10.  
  11. (SELECT *  
  12.  
  13. FROM [AdventureWorks].[HumanResources].[Employee] e  
  14.  
  15. WHERE 1=e.ContactID AND e.SickLeaveHours>68) 

step 2:

  1. SELECT [FirstName]  
  2.  
  3. ,[MiddleName]  
  4.  
  5. ,[LastName]  
  6.  
  7. FROM [AdventureWorks].[Person].[Contact] c  
  8.  
  9. WHERE EXISTS  
  10.  
  11. (SELECT *  
  12.  
  13. FROM [AdventureWorks].[HumanResources].[Employee] e/p> 
  14.  
  15. WHERE 2=e.ContactID AND e.SickLeaveHours>68) 

step n:

  1. SELECT [FirstName]  
  2.  
  3. ,[MiddleName]  
  4.  
  5. ,[LastName]  
  6.  
  7. FROM [AdventureWorks].[Person].[Contact] c  
  8.  
  9. WHERE EXISTS  
  10.  
  11. (SELECT *  
  12.  
  13. FROM [AdventureWorks].[HumanResources].[Employee] e  
  14.  
  15. WHERE n=e.ContactID AND e.SickLeaveHours>68) 

如上面代碼所示。上面的相關(guān)子查詢實際上會執(zhí)行N次(N取決與外部查詢的行數(shù)),外部查詢每執(zhí)行一行,都會將對應行所用的參數(shù)傳到子查詢中,如果子查詢有對應值,則返回TRUE(既當前行被選中并在結(jié)果中顯示),如果沒有,則返回FALSE。然后重復執(zhí)行下一行。

子查詢作為計算列使用

當子查詢作為計算列使用時,只返回單個值(Scalar) 。用在SELECT語句之后,作為計算列使用。同樣分為相關(guān)子查詢和無關(guān)子查詢

相關(guān)子查詢的例子比如:我想取得每件產(chǎn)品的名稱和總共的銷量。

  1. SELECT [Name],  
  2.  
  3. (SELECT COUNT(*) FROM AdventureWorks.Sales.SalesOrderDetail S  
  4.  
  5. WHERE S.ProductID=P.ProductID)AS SalesAmount  
  6.  
  7. FROM [AdventureWorks].[Production].[Product] P 

部分結(jié)果如下:

當子查詢作為計算列使用時,會針對外部查詢的每一行,返回唯一的值。

同樣的,SQL子查詢都可以使用其他語句達到同樣的效果,上面的語句和如下語句達到同樣的效果:

  1. SELECT P.Name,COUNT(S.ProductID)  
  2.  
  3. FROM [AdventureWorks].[Production].[Product] P  
  4.  
  5. LEFT JOIN AdventureWorks.Sales.SalesOrderDetail S  
  6.  
  7. ON S.ProductID=P.ProductID  
  8.  
  9. GROUP BY P.Name 

子查詢作為計算列且作為無關(guān)子查詢時使用,只會一次性返回但一值,這里就不再闡述了。

【編輯推薦】

  1. 誤刪SQL Server日志文件后怎樣附加數(shù)據(jù)庫
  2. 如何配置Oracle 10g oem中的主機身份證明
  3. 詳解Lotus Domino數(shù)據(jù)庫關(guān)鍵數(shù)據(jù)的保護(一)
  4. 詳解Lotus Domino數(shù)據(jù)庫關(guān)鍵數(shù)據(jù)的保護(二)
  5. SQL Server 2005數(shù)據(jù)庫用戶權(quán)限管理的設置
責任編輯:趙鵬 來源: 博客園
相關(guān)推薦

2011-10-19 10:07:16

T-SQL查詢變量

2011-08-24 16:36:00

T-SQL

2011-08-23 13:36:11

T-SQL查詢流程控制語句

2021-09-10 07:31:54

AndroidAppStartup原理

2023-12-16 13:14:00

SQL子查詢技術(shù)

2021-09-24 08:10:40

Java 語言 Java 基礎

2017-08-08 09:15:41

前端JavaScript頁面渲染

2021-09-08 06:51:52

AndroidRetrofit原理

2021-10-15 09:19:17

AndroidSharedPrefe分析源碼

2021-02-17 11:25:33

前端JavaScriptthis

2021-08-24 07:53:28

AndroidActivity生命周期

2021-09-18 06:56:01

JavaCAS機制

2017-04-21 11:24:13

數(shù)據(jù)庫Azure T-SQL編輯器

2011-08-12 10:31:01

T-SQL查詢基于列的邏輯表達式

2021-09-16 06:44:04

Android進階流程

2021-09-17 06:55:50

AndroidLayoutView

2022-08-02 14:11:50

nucleiWorkflowsMathcer

2014-07-15 17:17:31

AdapterAndroid

2025-01-13 07:30:00

SQL開發(fā)組合查詢

2018-12-27 12:34:42

HadoopHDFS分布式系統(tǒng)
點贊
收藏

51CTO技術(shù)棧公眾號