成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

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

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

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

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

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

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

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

上圖是作為數據源使用的一個子查詢。

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

返回一張數據表(Table)

返回一列值(Column)

返回單個值(Scalar)

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

子查詢作為數據源使用

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

比如這個語句:

  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,作為數據源(表)和Product表進行內連接。結果如下:

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

子查詢作為選擇條件使用

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

作為選擇條件的子查詢是那些只返回一列(Column)的子查詢,如果作為選擇條件使用,即使只返回單個值,也可以看作是只有一行的一列.比如,在AdventureWorks中:我想取得總共請病假天數大于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) 

結果如下:

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

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

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

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

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

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

用ANY關鍵字進行等效的查詢為:

  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關鍵字在子查詢中使用時,所實現的效果如下:

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

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

這里要注意,SQL是一種很靈活的語言,就像子查詢所實現的效果可以使用JOIN來實現一樣(效果一樣,實現思路不同),ANY和ALL所實現的效果也完全可以使用其他方式來替代,按照上面表格所示,>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#

相關子查詢和EXISTS關鍵字

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

我想取得總共請病假天數大于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) 

結果和使用IN關鍵字的查詢結果相同:

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

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

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

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

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

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

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

而相反,作為相關子查詢,子查詢的執行的次數依賴于外部查詢,外部查詢每執行一行,子查詢執行一次,比如:

還是上面的例子:我想取得總共請病假天數大于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) 

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

子查詢作為計算列使用

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

相關子查詢的例子比如:我想取得每件產品的名稱和總共的銷量。

  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 

部分結果如下:

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

同樣的,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 

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

【編輯推薦】

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

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子查詢技術

2021-02-17 11:25:33

前端JavaScriptthis

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-09-18 06:56:01

JavaCAS機制

2021-08-24 07:53:28

AndroidActivity生命周期

2011-08-12 10:31:01

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

2017-04-21 11:24:13

數據庫Azure T-SQL編輯器

2021-09-16 06:44:04

Android進階流程

2021-09-17 06:55:50

AndroidLayoutView

2018-12-27 12:34:42

HadoopHDFS分布式系統

2014-12-04 14:01:54

openstacknetworkneutron

2019-03-18 09:50:44

Nginx架構服務器

2014-07-15 17:17:31

AdapterAndroid
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国内精品视频在线观看 | 日韩成人影院 | 久草视 | 成人国产午夜在线观看 | 一区二区三区免费看 | 一级黄色av电影 | 亚洲精品视频在线播放 | 麻豆一区一区三区四区 | 久久久久久成人 | 黄色国产在线视频 | 亚洲欧美在线一区 | 久久综合国产精品 | 日韩欧美中文字幕在线观看 | 中文在线a在线 | 中文字幕一区在线观看视频 | 精品国产乱码久久久久久1区2区 | 天天色av| 国产精品揄拍一区二区 | 成人毛片一区二区三区 | 成人在线视频免费观看 | 欧美日韩综合一区 | 毛片在线看看 | 一区二区三区视频免费观看 | 日本一区二区高清不卡 | 国产精品久久久乱弄 | 成人黄色a | 最近日韩中文字幕 | 毛片高清 | 精品久久一区 | 亚洲电影一区二区三区 | 亚洲国产精品精华素 | 国产9 9在线 | 中文 | 午夜av毛片 | 91亚洲精选 | 亚洲精品日本 | 一区二区三区四区国产 | 久久久久中文字幕 | 欧美激情精品久久久久久免费 | 91视频免费视频 | 国产高清视频在线观看 | 久久成人免费视频 |