我可以稍后在同一视图中使用在 SQL Server 视图中计算的列吗?
Posted
技术标签:
【中文标题】我可以稍后在同一视图中使用在 SQL Server 视图中计算的列吗?【英文标题】:Can I use a column calculated in a SQL Server view later on in that same view? 【发布时间】:2011-12-21 20:10:58 【问题描述】:假设我有以下观点:
Select
t1.StartMile, t2.EndMile, t2.EndMile- t1.StartMile as TotMile
from
TableStarts as t1
inner join
TableEnds as t2 on t1.Id = t2.Id
有没有办法编辑视图以执行以下操作
Select
t1.StartMile, t2.EndMile, t2.EndMile - t1.StartMile as TotMile,
TotMile + 30 as EvenMoreMiles
我试过了,但报错:
列名“TotMile”无效
请不要告诉我使用t2.EndMile - t1.StartMile + 30 as EvenMoreMiles
。 TotMiles
在我的实际代码中是一个很长的 case 语句。
我宁愿不必创建中间视图。
我使用的是 SQL Server 2005。
稍后添加
感谢您的所有回答。我会全部投票。
答案提出了以下新问题:
鉴于有数千行,TotMiles
如下所示,给出的哪个答案最有效?还是创建中间视图最有效?
CASE WHEN t .TaskType = 1 and t .StartTime < '1/1/2012'
THEN (tv.EndMile - tv.StartMile )
WHEN NOT (t .Location1_PKey = c.pkey OR t .Location2_PKey = c.pkey)
then (tv.EndMile - tv.StartMile )
WHEN (tv.EndMile - tv.StartMile ) < 31 Then 0
ELSE (tv.EndMile - tv.StartMile - 30 )
END AS MilesAdjusted2012,
【问题讨论】:
当谈到效率问题时,答案通常是“视情况而定”——我们不知道你的数据是什么样的,你有什么索引等等。我们也不知道是否甚至假设最差的解决方案对于您的目的已经足够有效,或者我们表现最好的答案仍然不足以满足您的情况/ 谢谢达米安。我很懒。 【参考方案1】:您还可以使用更简洁的CROSS APPLY
,特别是在您构建引用前面的别名的别名链时。
SELECT t1.StartMile,
t2.EndMile,
TotMile,
EvenMoreMiles,
AndYetMoreMiles
FROM TableStarts AS t1
INNER JOIN TableEnds AS t2
ON t1.Id = t2.Id
CROSS APPLY (SELECT t2.EndMile - t1.StartMile) A(TotMile)
CROSS APPLY (SELECT TotMile + 30) A2(EvenMoreMiles)
CROSS APPLY (SELECT EvenMoreMiles + 100) A3(AndYetMoreMiles)
【讨论】:
请参阅我添加的效率问题部分 @LillLansey - 嵌套 CTE 或嵌套交叉应用都可能会评估一次表达式,如果这是您要问的?尽管您需要检查执行计划才能看到,但在这方面并不能保证太多。 @MartinSmith -CROSS APPLY
子句的顺序重要吗?您能否参考第一个子句中第二个子句中的字段?
@JNK - 是的,因为这个原因,你不能。【参考方案2】:
你不能直接,但你可以建立子选择:
select StartMile,EndMile,TotMile,TotMile+30 as EvenMoreMiles from (
Select t1.StartMile, t2.EndMile, t2.EndMile- t1.StartMile as TotMile
from
TableStarts as t1
inner join
TableEnds as t2
on t1.Id = t2.Id
) t
或者使用公用表表达式:
;with FirstCalcs as (
Select t1.StartMile, t2.EndMile, t2.EndMile- t1.StartMile as TotMile
from
TableStarts as t1
inner join
TableEnds as t2
on t1.Id = t2.Id
)
select StartMile,EndMile,TotMile,TotMile+30 as EvenMoreMiles from FirstCalcs
如果要建立最终计算的多个级别,我通常更喜欢使用 CTE,因为否则大多数格式化方案都难以使选择、子选择、子子选择等变得简单读书。 CTE 可以包含对先前定义的 CTE 的引用:
;with CTE1 as (
SELECT ...
), CTE2 as (
SELECT ... FROM CTE1
), CTE3 as (
SELECT ... FROM CTE2
), CTE4 as (
SELECT ... FROM CTE2 ... CTE3
)
SELECT ... FROM CTE4 ... CTE1
【讨论】:
请参阅我添加的效率问题部分【参考方案3】:尝试使用派生表。
SELECT
DerivedTable.*,
TotMile + 30 as EvenMoreMiles
From (Select
t1.StartMile,
t2.EndMile,
t2.EndMile- t1.StartMile as TotMile
FROM Table t1
Inner Join table2 t2 on t1.PK = t2.FK) DerivedTable
【讨论】:
请参阅我添加的效率问题部分【参考方案4】:您可以使用公用表表达式 (CTE) 来执行此操作。这里有很多:http://www.4guysfromrolla.com/webtech/071906-1.shtml
基本上,
CREATE VIEW ... AS
WITH Mileage (StartMile, EndMile, TotMile) AS (Select t1.StartMile, t2.EndMile, t2.EndMile- t1.StartMile as TotMile
from
TableStarts as t1
inner join
TableEnds as t2
on t1.Id = t2.Id)
SELECT TotMile FROM Mileage
【讨论】:
请参阅我添加的效率问题部分以上是关于我可以稍后在同一视图中使用在 SQL Server 视图中计算的列吗?的主要内容,如果未能解决你的问题,请参考以下文章