如何在表中指定基于SQL Server中另一列的计算列?

时间:2015-06-09 18:42:28

标签: sql sql-server sql-server-2012

我有下面的伪造数据。

我想更改Total_Investment列以使其成为计算列,该列计算该行中存在的单位名称的总Dollar_Amount。

例如,对于第1行,Total_Investment槽将显示列为' Healthy_Communities'的两行的总和,因此第1行和第6行,例如5899.00 + 1766.00。

第2行将对Urban条目的所有三个(2,5和9)求和,依此类推。如何在SQL Sever 2012中完成此操作?

Project_ID  Unit_Name             Fiscal_Year  Dollar_Amount  Total_Investment
1           Healthy Communities   2000-01-01   5899.00        0.00
2           Urban                 2009-01-01   6008.00        0.00
3           Rivers and Watersheds 2006-01-01   6835.00        0.00
4           Large Landscapes      2011-01-01   5216.00        0.00
5           Urban                 2015-01-01   3555.00        0.00
6           Healthy Communities   2014-01-01   1766.00        0.00
7           Youth Engagement      2004-01-01   4246.00        0.00
8           Rivers and Watersheds 2014-01-01   8253.00        0.00
9           Urban                 2000-01-01   5590.00        0.00
10          Outdoor Recreation    2013-01-01   5356.00        0.00

我知道计算列的alter table documentation但不知道如何修改此代码以适应我的问题。

2 个答案:

答案 0 :(得分:3)

是的,您将创建一个用户定义的函数来进行计算,并在Computed列的表达式中使用该用户定义的函数。

一个工作的例子就像......

CREATE TABLE TABLE1 (ID INT, VALUE INT)
GO
INSERT INTO TABLE1 VALUES (1 , 10), (2 , 20) , (3 , 30)
GO

CREATE FUNCTION dbo.udf_DefaultValue(@ID INT)
RETURNS INT
AS
BEGIN
    DECLARE @rtnValue INT;
    SELECT @rtnValue = VALUE *2 FROM TABLE1 WHERE ID = @ID
    RETURN @rtnValue;
END
GO

CREATE TABLE TABLE2 (ID INT
                  , VALUE INT
                  , ComputedColumn AS (VALUE * dbo.udf_DefaultValue(ID)) )
GO

INSERT INTO TABLE2 (ID , VALUE)
VALUES (1, 1)

SELECT * FROM TABLE2

/*****  Result Set  *****/

ID  VALUE   ComputedColumn
1     1           20

答案 1 :(得分:2)

仅将下面的MyTable替换为您的表名。 这种方法的缺点是,如果使用多行(例如,10000秒为10000),它变得非常昂贵。对于这种情况,您可以使用视图。 (感谢@Amit坚持使用UDF。抱歉,表现很糟糕)

编辑: 在Unit_Name添加了非聚集索引,包括Dollar_Amount。性能提高了十倍。

-- drop table MyTable;
-- drop function udfMyTable;

-- go

create table MyTable(
 project_id int identity(1, 1) primary key,
 Unit_Name varchar(120),
 Dollar_Amount decimal(19, 2),
)

go
create nonclustered index IX_Unit on dbo.MyTable(Unit_Name) include (Dollar_Amount);

create function udfMyTable (@pk as int)
returns decimal(19, 2)
as
begin
declare @res as decimal(19, 2);
select 
    @res=sum(Dollar_Amount) 
from 
    MyTable 
where Unit_Name in (select Unit_Name from MyTable where project_id=@pk);
return @res;
end
go
alter table MyTable add Total_Amount as dbo.udfMyTable(project_id)
go


insert into MyTable (unit_name, dollar_amount) values
('Healthy Communities',   '5899.00'),
('Urban',                 6008.00),
('Rivers and Watersheds', 6835.00),
('Large Landscapes',      5216.00),
('Urban',                 3555.00),
('Healthy Communities',   1766.00),
('Youth Engagement',      4246.00),
('Rivers and Watersheds', 8253.00),
('Urban',               5590.00),
('Outdoor Recreation', 5356.00)

select * from MyTable;