【问题标题】:formula for computed column based on different table's column基于不同表列的计算列公式
【发布时间】:2011-02-15 16:12:24
【问题描述】:

考虑这张表:c_const

 code  |  nvalue
 --------------
 1     |  10000
 2     |  20000  

还有一张桌子t_anytable

 rec_id |  s_id  | n_code
 ---------------------
 2      |  x     | 1

目标是让s_id 成为计算列,基于以下公式:

 rec_id*(select nvalue from c_const where code=ncode)

这会产生错误:

在这种情况下不允许子查询。只允许使用标量表达式。

如何使用另一个表的列作为输入来计算此计算列的值?

【问题讨论】:

  • @marc_s:没关系,谢谢你的帮助。

标签: sql sql-server-2008 calculated-columns


【解决方案1】:

您可以为此创建一个用户定义的函数:

CREATE FUNCTION dbo.GetValue(@ncode INT, @recid INT)
RETURNS INT
AS 
   SELECT @recid * nvalue 
   FROM c_const 
   WHERE code = @ncode

然后用它来定义你的计算列:

ALTER TABLE dbo.YourTable
   ADD NewColumnName AS dbo.GetValue(ncodeValue, recIdValue)

【讨论】:

  • 是否会在更新其他表时更新计算字段?
  • @littlestewie: 是的! 每次有一段代码访问NewColumnName 列时,都会调用该函数并计算值
  • @Binny, marc_s:我不会说 UDF 会像视图一样高效。视图对查询优化器是透明的,而 UDF 本质上是一个黑盒。 UDF 将有自己的执行计划,并且始终针对受影响的每一行运行,而视图将与查询的其余部分混合,并且始终为整个查询生成最佳执行计划 使用视图。
  • 在 Management Studio 中将计算字段的 IsPersisted 属性设置为 True。然后每次访问该字段时都不会重新计算它。或者在 DDL 中,在字段的公式之后添加 PERSISTED,例如ALTER TABLE dbo.YourTable ADD NewColumnName AS dbo.GetValue(ncodeValue, recIdValue) PERSISTED;
  • 值得注意的是,如果值是确定性的,您只能使用 PERSISTED - 详情请参阅docs.microsoft.com/en-us/sql/relational-databases/…
【解决方案2】:

这似乎更像是视图的工作(索引视图,如果您需要在计算列上快速查找):

CREATE VIEW AnyView
WITH SCHEMABINDING
AS

SELECT a.rec_id, a.s_id, a.n_code, a.rec_id * c.nvalue AS foo
FROM AnyTable a
INNER JOIN C_Const c
    ON c.code = a.n_code

这与子查询版本有细微的区别,如果连接有多个结果,它将返回多条记录而不是产生错误。但这很容易通过c_const.code 上的UNIQUE 约束来解决(我怀疑它已经是PRIMARY KEY)。

也比子查询版更容易让人理解。

您可以使用子查询和 UDF 来执行此操作,如 marc_s 所示,但与简单的 JOIN 相比,这可能高度效率低下,因为需要计算标量 UDF -逐行。

【讨论】:

  • 请注意,索引视图并不总是“快速查找” - 如果索引视图存储的行数与基表一样多(例如,它不是聚合),并且它不是也比基表瘦很多,它不会更快 - 在这种情况下,计算列是比索引视图恕我直言更好的选择。
  • ...或者如果它 is 比基表更瘦,但无论如何您仍然必须对基表进行联接以满足查询。根据我的经验,索引视图的主要优势一直是减少计算聚合的存储,而不是删除计算本身。
  • 我会修改我的评论,因为我显然没有在这里阅读整个上下文,也没有意识到要求是从不同的表中提取一个值。在这种情况下,索引视图可能是一个很好的解决方案,我的反对意见只是关于索引视图总是比普通视图或计算列更快的常见误解(并且在这里永久化)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-26
  • 1970-01-01
  • 1970-01-01
  • 2010-12-23
  • 2021-07-15
  • 2018-06-03
相关资源
最近更新 更多