标量函数作为计算列的一部分

时间:2015-07-27 11:11:28

标签: sql-server function calculated-columns

我正在使用SQL Server 2012.我想创建一个带有计算列的表。此列是此表中列的总和,但我需要将总和乘以VAT表中的增值税率,以获得包含税的总值。 VAT值每月插入VAT表中,并作为smallint存储在Stawka列中(英文中表示“Rate”)。 每月都会插入表格Prąd的值,因此我需要使用增值税表中Stawka列的当前增值税率。

因此,如果税率(VAT表中的列Stawka)目前是23%,那么这是简单的数学: (Y + Z)+ 23%*(Y + Z)=(Y + Z)*(1 + 0.23)=(Y + Z)* 1.23其中Y + Z是表中最后一列之前的十进制列之和PRAD。

来自表Prąd的行示例。在最后一列(计算列)下面,它只是0.2661 + 0.2103的总和。如上所述,首先我需要将0.2103和0.2661相加,然后将总和乘以1.23:

ID  Data    Rok Kwartał Miesiąc Dzień   Jednostka   Odczyt  Zużycie Energia elektryczna czynna  Opłata dystrybucyjna zmienna Stawka jednostkowa energii
1 2015-01-01 2015   1     1      1        kWh        300      20         0.2661                    0.2103                            0.4764

我不能对1.23进行硬编码,因为增值税率可能会发生变化,所以我决定创建一个增值税表,但我不知道如何在计算列内的Stawka列中使用这些值。

我尝试使用我在这里找到的一些技巧并使用标量函数来获取当前的增值税值并连接但似乎我不能将它作为整个计算的一部分使用。下面是一些代码:

我正在尝试创建的计算列表(创建表时弹出错误无效列“Stawka”):

    CREATE TABLE dbo.Prąd
(
ID INT NOT NULL IDENTITY (1,1),
Data DATE NOT NULL,
Rok AS YEAR(Data) PERSISTED NOT NULL,
Kwartał AS DATEPART(q,Data) PERSISTED NOT NULL,
Miesiąc AS MONTH(Data) PERSISTED NOT NULL,
Dzień AS DAY(Data) PERSISTED NOT NULL,
Jednostka VARCHAR (5) NULL,
Odczyt SMALLINT NOT NULL,
Zużycie SMALLINT NOT NULL,
[Energia elektryczna czynna] DECIMAL (9,4) NULL,
[Opłata dystrybucyjna zmienna] DECIMAL (9,4) NULL,
[Stawka jednostkowa energii] AS CAST (([Energia elektryczna czynna] + [Opłata dystrybucyjna zmienna])*('1.' + dbo.fnVAT(ID)) AS DECIMAL (9,4)) PERSISTED NOT NULL
)

增值税表:

CREATE TABLE dbo.VAT
(
ID INT NOT NULL IDENTITY (1,1),
Data DATE NOT NULL,
Stawka SMALLINT NOT NULL,
);

标量函数:

CREATE FUNCTION fnVAT (@VAT SMALLINT)

RETURNS SMALLINT

AS BEGIN

SELECT @VAT = Stawka FROM VAT AS V JOIN Prąd AS P ON V.ID = P.ID

RETURN @VAT

END

1 个答案:

答案 0 :(得分:2)

由于VAT取决于另一个表的内容,我认为不可能将该列创建为持久化。这意味着每次选择该列时,将为select中的每一行单独调用标量函数。这可能对性能非常不利,我不能真正推荐它,但如果你想这样做,这就是这样做的方法:

CREATE FUNCTION fnVAT (@DATE date)    
RETURNS decimal(3,2)    
AS BEGIN
    declare @VAT smallint

    SELECT top 1 @VAT = VAT FROM VAT where Date <= @DATE order by DATE desc 

    RETURN 1 + 0.01 * @VAT
END;

alter table Prad add VAT AS (Value1 + Value2) * dbo.fnVAT(Date)

我的例子是用这张表制作的:

CREATE TABLE Prad
    ([ID] int, [Date] date, [Value1] DECIMAL (9,4), [Value2] DECIMAL (9,4))

因为我认为不使用波兰语(?)列名更容易。

SQL Fiddle

中的示例

就像你说的那样,你也可以在一个触发器中做到这一点,这应该是一个更好的性能明智,因为那时获取只进行一次,并且由于增值税并没有真正改变,因此通常它可能是最好的主意。