2014-10-22 86 views
1

有一種方法,以具有從另一個表中的列具有值這始終是一個視圖>實施例內相同的:SQL Server的柱,從另一個表靜態值在View

SELECT *, 
    (SELECT value FROM tblStudentPrefixes WHERE PrefixName = 'SeniorPrefix') 
    AS StudentPrefix 
FROM tblStudents 

請問上述嵌套查詢從每一行開始執行?有沒有辦法執行一次並用於所有行。

請注意,我具體談論的是一個視圖,而不是一個存儲過程。我知道這可以在存儲過程中完成。

+0

如果你PrefixName是獨一無二的,你可以把它改寫作爲外連接 – 2014-10-22 09:22:53

回答

4

這實際上取決於你的表設置。除非prefixName被限制爲唯一的,否則可能會遇到錯誤,其中子查詢返回多行。如果它不被限制爲唯一的,但碰巧對於SeniorPrefix是唯一的,那麼您的查詢將被執行1000次。爲了證明我已經使用以下DDL:

CREATE TABLE #tblStudents (ID INT IDENTITY(1, 1), Filler CHAR(100)); 
INSERT #tblStudents (Filler) 
SELECT TOP 10000 NULL 
FROM sys.all_objects a, sys.all_objects b; 

CREATE TABLE #tblStudentPrefixes (Value VARCHAR(10), PrefixName VARCHAR(20)); 
INSERT #tblStudentPrefixes (Value, PrefixName) VALUES ('A Value', 'SeniorPrefix'); 

運行您的查詢提供了以下IO輸出:

Table '#tblStudentPrefixes'. Scan count 10000, logical reads 10000

Table '#tblStudents'. Scan count 1, logical reads 142

該鍵爲1000個邏輯讀取tblStudentPrefixes。另一個問題與它不被約束是獨一無二的,如果你有重複的查詢將失敗與錯誤:

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

如果你不能限制PrefixName是唯一的,那麼你可以停止執行每一行和使用TOP避免的錯誤:

SELECT *, 
    (SELECT TOP 1 value FROM #tblStudentPrefixes WHERE PrefixName = 'SeniorPrefix' ORDER BY Value) 
    AS StudentPrefix 
FROM #tblStudents 

的IO現在變成:

Table '#tblStudentPrefixes'. Scan count 1, logical reads 1

Table '#tblStudents'. Scan count 1, logical reads 142

不過,我想STILL R ecommend切換到交叉連接的位置:

SELECT s.*, p.Value AS StudentPrefix 
FROM #tblStudents AS s 
     CROSS JOIN 
     ( SELECT TOP 1 value 
      FROM #tblStudentPrefixes 
      WHERE PrefixName = 'SeniorPrefix' 
      ORDER BY Value 
     ) AS p; 

的執行計劃檢驗示出了使用表線軸,其是一個單值非常不必要子選擇:

enter image description here

所以在總結,它取決於你的表設置是否會爲每行執行,但不管你是否給予優化器一個更好的機會,如果你切換到交叉連接。


編輯

在你需要從tblstudent返回行的時候沒有匹配的tblStudentPrefixesSeniorPrefix事實輕,而且PrefixName不currenty constrianed是唯一的,則最好解決方法是:

SELECT *, 
    (SELECT MAX(value) FROM #tblStudentPrefixes WHERE PrefixName = 'SeniorPrefix') 
    AS StudentPrefix 
FROM #tblStudents; 

如果您確實將其限制爲唯一,那麼以下3個查詢會生成(essentiall Y)相同的計劃和相同的結果,它只是個人喜好:

SELECT *, 
    (SELECT value FROM #tblStudentPrefixes WHERE PrefixName = 'SeniorPrefix') 
    AS StudentPrefix 
FROM #tblStudents; 

SELECT s.*, p.Value AS StudentPrefix 
FROM #tblStudents AS s 
     LEFT JOIN #tblStudentPrefixes AS p 
      ON p.PrefixName = 'SeniorPrefix'; 

SELECT s.*, p.Value AS StudentPrefix 
FROM #tblStudents AS s 
     OUTER APPLY 
     ( SELECT Value 
      FROM #tblStudentPrefixes 
      WHERE PrefixName = 'SeniorPrefix' 
     ) AS p; 
+0

謝謝。在檢查SO上的答案之前,我嘗試了以下給出了期望的結果。你認爲你的查詢會有更好的表現嗎? 'SELECT s。*,p.Value AS StudentPrefix FROM tblStudents s LEFT JOIN tblStudentPrefixes ON p.PrefixName ='SeniorPrefix'' – user3656029 2014-10-22 08:44:19

+0

這取決於,但我懷疑它。如果LEFT JOIN被限制爲唯一的,那麼使用'LEFT JOIN'就可以得到與上述子選擇相同的延遲假脫機問題,如果它不是唯一的,那麼嵌套循環連接的問題就會相同, tblStudentPrefixes。 – GarethD 2014-10-22 08:56:05

+0

我想關鍵的問題是,tblStudentPrefixes中的「SeniorPrefix」總會有值嗎?如果沒有,你想返回結果嗎? – GarethD 2014-10-22 08:57:47

0

這是好的。每行中的每一行都會執行子查詢(這可能會導致性能下降)。 你也試試:

SELECT tblStudents.*,StudentPrefix.value 
    FROM tblStudents, 
     (SELECT value 
     FROM tblStudentPrefixes 
     WHERE PrefixName = 'SeniorPrefix')StudentPrefix 
1

我希望我明白你的問題的權利,但試試這個

SELECT * 
FROM tblStudents 
Outer Apply 
    (
    SELECT value 
    FROM tblStudentPrefixes 
    WHERE PrefixName = 'SeniorPrefix' 
    ) as tble 
相關問題