SQL Server 计算列从另一张表中选择

40

我不太确定应该如何最好地处理这个问题,因此我将描述最终目标,如果计算列是答案,请帮助我走这条路线,或者可能有更好的路线。

我有两个表:

订单(Orders)

OrderId
PackageId
MediaSpend
TotalAdViews (Computed column)

软件包

PackageId
BaseAdViews
每个订单都会分配一个含有1,000个视图的套餐,您可以购买更多的媒体支出来获得更多的视图。我想创建一个名为TotalAdViews的列,它将添加BaseAdViews和MediaSpend。据我所知,如果启用了持续性,则不需要每次查询时重新计算该列,这可能有助于提高性能。
如何从另一个表中获取计算列中的值?或者请提供实现我的目标的替代方法。
3个回答

97

我知道这个答案晚了两年,但是为了帮助任何通过谷歌搜索并找到这篇文章的人:

定义用户定义函数并将其用作计算值是完全合法的。此函数可以包含来自其他表的select语句。

CREATE FUNCTION dbo.getAdViews(@packageId int)
RETURNS INT
AS
BEGIN
    declare @bav int
    select @bav = BaseAdViews from Packages where PackageId = @packageId
    RETURN @bav
END

那么在你的计算列中,只需使用表达式 dbo.getSumAdViews(PackageId)+MediaSpend,如下所示:

CREATE TABLE [dbo].[Orders](
    [OrderId] [int] IDENTITY(1,1) NOT NULL,
    [PackageId] [int] NOT NULL,
    [MediaSpend] [int] NULL,
    [TotalAdViews] AS dbo.getAdViews(PackageId)+MediaSpend
) ON [PRIMARY]

1
这种方法在性能方面与直接连接相比如何? - liang
6
没问题,只需注意一点,如果您希望保留计算列,这种方法将不起作用。 - Leonardo Spina
2
@liang 使用用户定义函数的计算列对性能不利,因为查询优化器无法扩展到用户定义函数。 - erkinyldz
3
由于UDF是非确定性的,你无法将此列设置为持久化。仅确定性列可被持久化。UDF中的任何SELECT都会使其变为非确定性。参考链接:https://learn.microsoft.com/en-us/sql/relational-databases/user-defined-functions/deterministic-and-nondeterministic-functions - Sebastian Zaklada
2
虽然标量UDF或多语句UDF强制查询计划放弃并行处理,但如果您可以将函数转换为内联表值函数,则效率与没有UDF一样高。我已更新我的答案以给出这样一个示例。 - Göran Roseen
显示剩余6条评论

23

在计算列表达式中,您将无法使用另一个表中的列。这是来自MSDN文档的摘录。

计算列是从可以使用同一表中的其他列的表达式计算出来的。

您提到使用计算列的动机是为了提高性能。虽然有很多限制,但索引视图可能会增加价值。


1
这个答案现在已经过时了,需要更新过去12年的SQL Server版本。 - Dai

5
如果仅用于显示目的,为什么不创建一个视图..
select <<add other columns you need>> mediaspend+basicadviews as totaladviews
from 
orders o
join
packages p
on p.packageid=o.orderid

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接