我有一个持久化的计算列,用于保存从DATETIME2
时间列([可能是不良时间])计算出的FLOAT
。我正在使用DATEADD
处理所有时间的下溢和上溢,但由于我无法弄清楚如何将它们存储在变量中,因此目前不得不不断重新计算整个公式中的相同值!实际的实现还支持年,月和日,但是有210行,所以这里是仅使用时间成分的简化版本
CREATE TABLE Sales
(
[Id] INT IDENTITY(1,1) NOT NULL,
[Potentially Bad Time] FLOAT NOT NULL,
CONSTRAINT PK_Sales PRIMARY KEY
(
Id ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE Sales
ADD [Time] AS
DATEADD
(
HOUR,
IIF
(
ROUND([Potentially Bad Time] / 10000, 0, 1) < 0,
--Subtracts underflowing hours.
ROUND([Potentially Bad Time] / 10000, 0, 1),
IIF
(
ROUND([Potentially Bad Time] / 10000, 0, 1) >= 24,
--Adds overflowing hours.
ROUND([Potentially Bad Time] / 10000, 0, 1) - 24,
0
)
),
DATEADD
(
MINUTE,
IIF
(
ROUND([Potentially Bad Time] / 100, 0, 1) - ROUND([Potentially Bad Time] / 10000, 0, 1) * 100 < 0,
--Subtracts underflowing minutes.
ROUND([Potentially Bad Time] / 100, 0, 1) - ROUND([Potentially Bad Time] / 10000, 0, 1) * 100,
IIF
(
ROUND([Potentially Bad Time] / 100, 0, 1) - ROUND([Potentially Bad Time] / 10000, 0, 1) * 100 >= 60,
--Adds overflowing minutes.
ROUND([Potentially Bad Time] / 100, 0, 1) - ROUND([Potentially Bad Time] / 10000, 0, 1) * 100 - 60,
0
)
),
DATEADD
(
SECOND,
--If the seconds value is greater than or equal to 60, this adds on the overflowing seconds to the relevant DATETIME2 component(s).
IIF
(
ROUND([Potentially Bad Time], 0, 1) - ROUND([Potentially Bad Time] / 100, 0, 1) * 100 < 0,
--Subtracts underflowing seconds.
ROUND([Potentially Bad Time], 0, 1) - ROUND([Potentially Bad Time] / 100, 0, 1) * 100,
IIF
(
ROUND([Potentially Bad Time], 0, 1) - ROUND([Potentially Bad Time] / 100, 0, 1) * 100 >= 60,
--Adds overflowing seconds.
ROUND([Potentially Bad Time], 0, 1) - ROUND([Potentially Bad Time] / 100, 0, 1) * 100 - 59,
0
)
),
DATEADD
(
MILLISECOND,
IIF
(
[Potentially Bad Time] - ROUND([Potentially Bad Time], 0, 1) < 0,
--Subtracts underflowing milliseconds.
[Potentially Bad Time] - ROUND([Potentially Bad Time], 0, 1),
IIF
(
[Potentially Bad Time] - ROUND([Potentially Bad Time], 0, 1) > 9999999,
--Adds overflowing milliseconds.
[Potentially Bad Time] - ROUND([Potentially Bad Time], 0, 1) - 9999999,
0
)
),
DATETIME2FROMPARTS
(
--Year (Fixed for brevity of example)
1990,
--Month (Fixed for brevity of example)
12,
--Day (Fixed for brevity of example).
31,
--Hour
IIF
(
ROUND([Potentially Bad Time] / 10000, 0, 1) < 0,
0,
IIF
(
ROUND([Potentially Bad Time] / 10000, 0, 1) >= 24,
23,
ROUND([Potentially Bad Time] / 10000, 0, 1)
)
),
--Minute
IIF
(
ROUND([Potentially Bad Time] / 100, 0, 1) - ROUND([Potentially Bad Time] / 10000, 0, 1) * 100 < 0,
0,
IIF
(
ROUND([Potentially Bad Time] / 100, 0, 1) - ROUND([Potentially Bad Time] / 10000, 0, 1) * 100 >= 60,
59,
ROUND([Potentially Bad Time] / 100, 0, 1) - ROUND([Potentially Bad Time] / 10000, 0, 1) * 100
)
),
--Second
IIF
(
--If the seconds value is less than 0, truncates it to 0.
ROUND([Potentially Bad Time], 0, 1) - ROUND([Potentially Bad Time] / 100, 0, 1) * 100 < 0,
0,
--If the seconds value is greater than or equal to 60, this truncates it at 59.
IIF
(
ROUND([Potentially Bad Time], 0, 1) - ROUND([Potentially Bad Time] / 100, 0, 1) * 100 >= 60,
59,
ROUND([Potentially Bad Time], 0, 1) - ROUND([Potentially Bad Time] / 100, 0, 1) * 100
)
),
--Millisecond
IIF
(
[Potentially Bad Time] - ROUND([Potentially Bad Time], 0, 1) < 0,
0,
IIF
(
[Potentially Bad Time] - ROUND([Potentially Bad Time], 0, 1) > 9999999,
9999999,
[Potentially Bad Time] - ROUND([Potentially Bad Time], 0, 1)
)
),
3
)
)
)
)
)
PERSISTED
例如,如何将[Time] - ROUND([Time], 0, 1)
放在名为@milliseconds
的变量中以保存多次计算?
我尝试了标量函数,因此该参数可以有效地成为变量,但是Persisted Computed列不支持使用标量函数(无论如何它们对于性能而言都是坏消息!)。
我还在DECLARE @milliseconds FLOAT = [Time] - ROUND([Time], 0, 1)
和公式之间尝试过AS
,但这是语法错误。
答案 0 :(得分:0)
您需要添加select来为变量分配一个值。
DECLARE @milliseconds FLOAT = ( select [Time] -
ROUND([Time], 0, 1) from yourtable);