翻译:通向T-SQL的阶梯:超越基础水平3:建立相关子查询
原文鏈接:http://www.sqlservercentral.com/articles/Stairway+Series/105972/ ? 原文作者:Gregory Larsen
該系列
本文是樓梯系列的一部分:通向T-SQL的階梯:超越基礎水平
從他的t - sql DML樓梯后,格雷戈里·拉森涵蓋了更高級的子查詢等方面的t - sql語言。
在2級樓梯我討論了如何使用數據庫引擎執行子查詢的sql語句。 這樓梯水平將擴大在子查詢主題討論類型的子查詢稱為相關subquery。 我將探索什么是相關子查詢,以及它是如何不同于正常的子查詢。 另外我將提供你一些Transaction-SQL語句的例子超越基本知識和使用相關子查詢來幫助識別行返回的結果集,以滿足復雜的業務需求。
相關子查詢是什么?
在2級樓梯我們了解到一個正常的子查詢只是一個SELECT語句在數據庫引擎執行另一個sql語句,子查詢可以返回結果,如果獨立運行的外部查詢。 相關子查詢是一種外的子查詢,不能獨立運行查詢,因為它包含一個或多個列從外部查詢。 相關子查詢,就像一個正常的子查詢,有時被稱為內部查詢。 如果相關子查詢(內部查詢)獨立運行的外部查詢將返回一個錯誤。 因為內部查詢的執行取決于價值觀從外部查詢,它被稱為相關子查詢。
相關子查詢可能多次執行。 它將為每個選定的候選人行運行一次外層查詢。 每個候選人一行的列值將用于供應值外查詢中的列內的每個執行相關子查詢。 最后聲明,包含一個相關子查詢的結果將基于每個執行相關子查詢的結果。
樣本數據的相關子查詢的例子
為了演示如何使用相關子查詢我需要一些測試數據。 而不是創建我自己的測試數據,我將使用一個示例AdventureWorks2008R2數據庫。 如果你想跟隨并運行在您的環境中我的例子你可以下載AdventureWorks2008R2數據庫從這里:http://msftdbprodsamples.codeplex.com/releases/view/93587
相關子查詢的WHERE子句的例子
展示相關子查詢的WHERE子句使用假設,我想按順序確定購買了超過70件的顧客的ID。 完成這個需求我可以運行清單1中的代碼。
SELECT CustomerID FROM Sales.SalesOrderHeader OH WHERE (SELECT COUNT(*) FROM Sales.SalesOrderDetail WHERE SalesOrderID = OH.SalesOrderID) > 70;清單1:相關子查詢的WHERE子句
當我運行清單1中的代碼報告1中得到的輸出。 CustomerID ----------- 29712 29722 30048 30107
報告1:運行清單1中的代碼時返回結果
如果你檢查代碼在清單1中您將看到我約束,通過使用相關子查詢。 括號內的子查詢的代碼我已經提取了相關子查詢代碼與清單1和清單2中把它。
SELECT COUNT(*) FROM Sales.SalesOrderDetail WHERE SalesOrderID = OH.SalesOrderID清單2:子查詢代碼在清單1中
如果我運行清單2中的代碼將會發現我得到一個錯誤顯示在報告2。
Msg 4104, Level 16, State 1, Line 3 The multi-part identifier "OH.SalesOrderID " could not be bound.報告2:運行時錯誤代碼在清單2中
我得到報告2所示的錯誤,因為相關子查詢列包含一個引用哦。 SalesOrderID列從外部查詢。 因為所有相關子查詢引用一個或多個列外查詢不能獨立地運行它們的外層查詢與之相關的。 你不能獨立運行子查詢整個transact - sql語句的區分在一個正常的子查詢相關子查詢。
這里給出的例子是一個非常簡單的例子在WHERE子句中使用相關子查詢。 希望通過這樣一個簡單的例子是很容易理解的區別正常的子查詢和相關子查詢。 典型相關子查詢可能更加復雜。 此外,記住可能有其他方法來滿足您的業務需求不相關子查詢。
正如你所看到的寫相關子查詢非常類似于一個正常的子查詢,但你不能獨立于外部查詢運行相關子查詢。
相關子查詢的例子HAVING子句
有些時候你可能需要限制條款由外層查詢不同的值。 這是當你可以使用子查詢相關條款。 假設你要編寫一個查詢,計算退稅金額的客戶購買了價值超過150000美元稅收在2008年前的產品。 清單3中的代碼計算退稅金額為那些有價值的客戶通過使用相關子查詢的條款。
SELECT Outer_H.[CustomerID] , SUM(Outer_H.[SubTotal]) AS TotalPurchase, SUM(Outer_H.[SubTotal]) * .10 AS Rebate FROM [Sales].[SalesOrderHeader] AS Outer_H WHERE YEAR(Outer_H.[OrderDate]) = '2008' GROUP BY Outer_H.[CustomerID] HAVING (SELECT SUM(Inner_H.[SubTotal]) FROM [Sales].[SalesOrderHeader] AS Inner_HWHERE Inner_H.[CustomerID] = Outer_H.[CustomerID]AND YEAR(Inner_H.[OrderDate]) = '2008') > 150000 ORDER BY Rebate DESC;清單3:相關子查詢在條款
當我運行清單5中的代碼報告3中得到結果。
CustomerID TotalPurchase Rebate ----------- --------------------- --------------------------------------- 29923 220496.658 22049.665800 29641 210647.4929 21064.749290 29617 187964.844 18796.484400 29913 186387.5613 18638.756130 29818 179916.2877 17991.628770 29940 175358.3954 17535.839540 29987 172169.4612 17216.946120 29736 157700.6034 15770.060340 29995 156984.5148 15698.451480 29770 151824.9944 15182.499440報告3:運行清單3的結果
在清單3中使用的相關子查詢代碼CustomerID外GROUP BY子句的查詢相關子查詢。 相關子查詢會為每一行執行一次返回的GROUP BY子句。 這允許有條款計算每個產品的總量CustomerID從外部查詢的值而得到的小計列在每個SalesOrderHeader記錄相關的記錄CustomerID從外部查詢。 清單3中的transact - sql語句,只返回一行CustomerID在購買了超過150000美元的產品。
一個更新語句的例子,其中包含相關子查詢
相關子查詢不僅可以用于使用SELECT語句返回一個結果集。 您也可以使用它們在SQL服務器更新數據表。 為了證明這一點,我首先會生成一些測試數據下邊表,通過使用清單4中的代碼
?
USE tempdb; GO SET NOCOUNT ON; CREATE TABLE CarInventory ( ID int identity, CarName varchar(50), VIN varchar(50), StickerPrice decimal (7,2), InvoicePrice decimal (7,2)); GO INSERT INTO CarInventory VALUES ('Explorer','EXP2014123456A',46198.45,38201.87), ('Explorer','EXP2014123493A',47129.98, 38201.87), ('Grand Cherokee','JGC20141234345X',41678.45,36201.86), ('Grand Cherokee','JGC20141234556W',44518.31,36201.86), ('Pathfinder','NPF2014987365A',32587.73,28917.10), ('Pathfinder','NPF2014239657B',33577.54,28917.10), ('Pathfinder','NPF2014098587C',35876.12,28917.10), ('Tahoe','TAH201409674A',52001.08,46000.01);清單4:代碼來創建和填充測試表
清單4中的代碼創建了一個CarInventory表,然后填充用八行代表汽車目前在庫存。
定期銷售經理喜歡看到他InvoicePriceRatio通過運行清單5中的查詢
SELECT CarName, InvoicePrice/StickerPrice*100.0 AS InvoicePriceRatio FROM CarInventory;清單5:InvoicePriceRatio查詢
當經理運行該查詢,她注意到有許多類似的汽車一樣InvoicePrice數量有不同InvoicePriceRatio值。 最大化發票標價比她問她的IT支持編寫一個查詢,該查詢將更新StickerPrice在她所有的汽車每輛車相同CarName?有相同的價值InvoicePriceRatio。 她希望這家伙來設置StickerPrice相同的值作為最高標價CarName。 這樣所有的汽車一樣CarName都有相同的價值StickerPrice價值。 完成這個更新的CarInventory表,這家伙運行清單6中的transact - sql語句,其中包含相關子查詢。
UPDATE CarInventory SET StickerPrice = (SELECT MAX(StickerPrice) FROM CarInventory Inner_CI WHERE Inner_CI.CarName = Outer_CI.CarName) FROM CarInventory Outer_CI;清單6:相關子查詢來更新CarInventory最大標價
清單8中的代碼使用CarName從外部查詢的相關子查詢來確定最大StickerPrice為每一個獨特的CarName。 這個最大StickerPrice然后使用相關子查詢中找到的值來更新StickerPrice值為每個CarInventory有相同的記錄CarName。
相關子查詢的性能注意事項
有些性能考慮你應該意識到寫作時transact - sql語句包含相關子查詢。 性能不是壞當外層查詢包含一個小的行數。 但當外層查詢包含大量的行不規模從性能角度來看。 這是因為相關子查詢中的每個候選人需要執行行外部查詢。 因此,當外部查詢包含越來越多的候選人行相關子查詢多次執行,因此transact - sql語句將需要更長的時間。 如果你發現你的相關子查詢transact - sql語句的性能沒有達到您的需求,那么您應該尋找替代解決方案,比如使用一個內部或外部連接操作的查詢,或返回一個小數量的候選人的行從外部查詢。
總結
相關子查詢是一種內在的查詢,包括一個或多個列從外部查詢。 相關子查詢是每個外部的候選人行執行一次查詢。 因為相關子查詢包含一個列外查詢不能獨立運行的外部查詢。 相關子查詢的地方,雖然沒有很好地擴展從性能角度來看當有大量的候選人中確定行外部查詢。
問題和答案
在本節中,您可以檢查你如何理解相關子查詢的概念通過回答下列問題。
問題1
編寫相關子查詢時需要___________________。 (填入空白)
1、一個或多個列的內部查詢用于限制相關子查詢的結果。
2、一個或多個列的內部查詢所使用的選擇列表相關子查詢。
3、一個或多個列從外部查詢用于限制相關子查詢的結果。
4、一個或多個列從外部查詢所使用的選擇列表相關子查詢。
問題2
選擇所有的以下相關子查詢語句,是正確的
1、隨著候選人的行數的增加性能數據庫引擎執行的sql語句,其中包含一個相關子查詢得到改善。
2、每個候選人的相關子查詢會執行一次行從外部查詢。
3、相關子查詢會引用一個或多個列的內部查詢。
4、當使用子查詢相關條款內查詢將對每個候選人行執行一次返回的GROUP by子句。
問題3:
相關子查詢就像一個正常的子查詢,和相關子查詢可以運行獨立于整個transact - sql語句(真或假)。
答案:
問題1:
正確答案是c。相關子查詢需要的一個或多個列外查詢相關子查詢語句中使用。 這些外列引用替換為值在執行每個候選人行相關子查詢。
問題2:
正確答案是b和d是不正確的,因為隨著候選人的行數的增加相關子查詢被多次執行,和數據庫引擎執行的sql語句的性能惡化。 c是錯誤的,因為相關子查詢必須包含一個或多個行從外部查詢,而不是內在的查詢。
問題3:
正確的答案是b。如果你嘗試運行數據庫引擎執行完整的sql語句的獨立相關子查詢,相關子查詢語句將失敗。
轉載于:https://www.cnblogs.com/705xinguan/p/7873382.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的翻译:通向T-SQL的阶梯:超越基础水平3:建立相关子查询的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 准确率(Accuracy), 精确率(P
- 下一篇: 基于类的访问权限