2017-12-27 340 views
1

這似乎是與SQL一般一個重大問題:T-SQL是否提供簡單的,不是過度設計的方式來減少子查詢的代碼重複? (沒有臨時表等)

SELECT 
    A, B, C, 
    ... 
    X, Y, 
    (
     SELECT TOP 1 
      b.R 
     FROM (
      SomeHugeSubqueryThatInclduesAWhereClause 
     ) b 
     ORDER BY 
      b.R 
    ) AS Z 
FROM (
    AlmostTheSameSubqueryThatIncludesAnOnlySlightlyDifferentWhereClause 
) a 

使用子查詢像這樣的代碼重複的問題。這裏有幾個解決方法,包括臨時表,存儲過程等。

這些解決方法至少有一個問題是它們相對參與某些更通用的語言只需要一個代碼行。其他語言允許你快速添加一個真正的變量並且繼續引用它,即使變量引用的對象具有延遲執行迭代器或其他東西。

臨時表可能抗衡一點與延遲執行的想法。視圖,存儲過程和函數會增加數據庫模式,並使其部署和更新變得更加複雜。以上所有內容都添加了幾行樣板代碼,只是覺得像一些簡單的過度工程。

所以,問題是...是否有一個良好的,通用的方法,以避免在這樣的情況下重複代碼,而無需東西,感覺過度設計和自行添加幾行?

+3

是。它被稱爲與'WITH'關鍵字一起引入的公用表表達式(CTE)。 –

+1

CTE只能用於其後的一個選擇中。如果您需要重用更多的選擇相同的查詢,你可以使用視圖一旦保存代碼,或接受參數,你可以在你的WHERE子句 – sepupic

+1

@sepupic使用TVF(內聯函數)只是爲了澄清,也可以是多個的CTE與嵌套引用,但最終的結果被限制到所證明在[本](https://stackoverflow.com/a/2140764/92546)回答一個單一的,可能複雜的,語句。 – HABO

回答

5

可以與公用表表達式(CTE)做到這一點。它看起來是這樣的:

with s as (
     <some huge subquery> 
    ) 
select . . . 
     (select top 1 b.r 
     from s b 
     order by b.r 
     ) AS Z 
from (select s.* 
     from s 
     where . . . 
    ) a; 

然而,你也許可以做你想做只是窗口函數是什麼:

select s.* 
from (select s.*, min(b.r) over() as min_r 
     from s 
    ) s 
where . . .; 
相關問題