2017-12-27 302 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 . . .;