在 SELECT 和 WHERE 子句中重用复杂的非确定性表达式

car*_*reo 2 sql-server t-sql sql-server-2008-r2

我有一个这样的查询:

-- This is inefficient, and may even be wrong if expression is nondeterministic
SELECT TOP 10 team_name,score_points=<big expression>
  FROM teams
 WHERE <big expression> >= 100
 ORDER BY 2 DESC

-- This gives error
SELECT TOP 10 team_name,score_points=<big expression>
  FROM teams
 WHERE score_points >= 100
 ORDER BY 2 DESC
Run Code Online (Sandbox Code Playgroud)

我想要做的很明确:列出得分最高的球队。列出所有得分至少为 100 score_points 的球队,但不超过 10 支球队。

如果我重复这个表达式,它将非常丑陋且效率低下。另外,当我的表达式不确定时,它会给出错误的结果。score_pointsWHERE子句中使用名称会出错。有没有一种有效的方法可以让我的表达式的结果既作为查询中的列返回,又用作过滤器?

请不要告诉我有关计算列的信息,我知道它们,但我不能在这里使用它们。

JNK*_*JNK 6

这对确定性问题没有帮助,但CROSS APPLY对于需要重用的大型表达式是一个很好的工具:

SELECT TOP 10 team_name, CxA.Score_Points
FROM teams t
CROSS APPLY (SELECT Score_Points = <big Expression, refer to t>) CxA
 WHERE CxA.Score_Points >= 100
 ORDER BY CxA.Score_Points DESC
Run Code Online (Sandbox Code Playgroud)

CROSS APPLY 表达式为每一行计算,可以在查询的任何部分引用。

  • 这“很有可能”有效,但不能保证。SQL Server 不保证表达式计算的时间或次数。即使从查询文本看来“明显”评估只发生一次,优化器也可能会生成具有不同运行时特征的计划。 (2认同)