MS SQL Server 2014
表模式(一部分)如下所示:
其中Coinh1d_Close
的类型为 float。
出于分析目的,我需要另一列,更精确地计算列,Coinh1d_EMA12
基于Coinh1d_Close
和先前值本身。第一个值始终是已知的,仅基于Coinh1d_Close
计算。必须根据Coinh1d_Close
和同一列Coinh1d_EMA12
的上一个值计算以下值,例如在Excel中:
从Calculating value using previous value of a row in T-SQL我写了一些T-SQL表达式
;with cteCalculation as (
select t.Coinh1d_Id, t.Coinh1d_Time, t.Coinh1d_Close, t.Coinh1d_Close as Column2
from Coinsh1d t
where t.Coinh1d_Id in (1)
union all
select t.Coinh1d_Id, t.Coinh1d_Time, t.Coinh1d_Close, cast(t.Coinh1d_Close as float)*cast(2 as float)/(cast(12 as float)+cast(1 as float))+cast(c.Column2 as float)*(cast(1 as float)-cast(2 as float)/(cast(12 as float)+cast(1 as float))) as Column2
from Coinsh1d t
inner join cteCalculation c
on t.Coinh1d_Id-1 = c.Coinh1d_Id
where t.Coinh1d_Name='BTC'
) select c.Coinh1d_Id, c.Coinh1d_Time, c.Coinh1d_Close, c.Column2
from cteCalculation c option (maxrecursion 0)
它完全符合我的需要
但是我的问题是可以使用计算列的先前值作为下一个值(我使用计算列的UDF函数)。我需要来自这个问题Calculating value using previous value of a row in T-SQL,但是对于Computed Column。
已更新
更多信息需要澄清:此表包含1000个硬币(BTC,ETH等)的数据,每个硬币的信息以特定时间Coinh1d_Time
(Unix时间戳)= 1346976000开头。在开始时我们加载从这个时间到当前时间(约2 000 000条记录)的所有信息,然后每小时t-sql脚本更新此表(添加1000行 - 每小时新数据)。
此表还有许多计算列(包括一个取决于Coinh1d_EMA12
)。
如果不能为Coinh1d_EMA12
创建计算列,我会看到解决方案:首先创建ordynary列Coinh1d_EMA12
。然后一次更新所有表
ALTER PROCEDURE [dbo].[UpdateEMA12h1d_notused]
-- Add the parameters for the stored procedure here
@Coin varchar(50)
AS
BEGIN
SET NOCOUNT ON;
print @coin
;with cte as (
select
t.Coinh1d_Id, t.Coinh1d_Close, t.Coinh1d_Close as Column2
from
Coinsh1d t
where
t.Coinh1d_Id in (select MIN(Coinh1d_Id) from Coinsh1d where Coinh1d_Name=@Coin)
union all
select
t.Coinh1d_Id, t.Coinh1d_Close, cast(t.Coinh1d_Close as float)*cast(2 as float)/(cast(12 as float)+cast(1 as float))+cast(c.Column2 as float)*(cast(1 as float)-cast(2 as float)/(cast(12 as float)+cast(1 as float))) as Column2
from
Coinsh1d t
inner join
cte c
on
t.Coinh1d_Id-1 = c.Coinh1d_Id
where
t.Coinh1d_Name=@Coin
)
select
c.Coinh1d_Id, c.Column2
into
#tempEMA12
from
cte c
option
(maxrecursion 0)
update
t1
set
t1.Coinh1d_Ema12 = t2.Column2
from
Coinsh1d as t1
inner join
#tempEMA12 as t2
on
t1.Coinh1d_Id = t2.Coinh1d_Id
drop table #tempEMA12
END
要求每一枚硬币:
DECLARE @MyCursor CURSOR;
DECLARE @MyField varchar(50);
BEGIN
SET @MyCursor = CURSOR FOR
select Coin_Symbol from Coins
OPEN @MyCursor
FETCH NEXT FROM @MyCursor
INTO @MyField
WHILE @@FETCH_STATUS = 0
BEGIN
exec UpdateEMA12h1d_notused @MyField
FETCH NEXT FROM @MyCursor INTO @MyField
END;
CLOSE @MyCursor ;
DEALLOCATE @MyCursor;
END;
大约需要30分钟。然后使用上面的CTE代码为此列创建触发器。
答案 0 :(得分:0)
从函数中的数据开始,您可以使用LAG()
(如果在SQL Server 2012或更高版本上)窗口函数将前一个值放在同一行中。代码将遵循此架构:
SELECT
C.CoinID,
C.CoinTime,
C.CoinClose,
C.FunctionComputedColumn,
PreviousRowFunctionComputedColumn =
LAG(
C.FunctionComputedColumn, -- The column you need from the previous row
1, -- How many rows back you need to go
0) -- Which value should it take if there is no previous row
OVER (
PARTITION BY
CoinID -- Row ordering resets with each different CoinID
ORDER BY
CoinTime ASC) -- Since it's ascending, the previous one is older
FROM
CoinData AS C
ORDER BY
C.CoinID,
C.CoinTIme
然后,您可以在所需的任何表达式中使用PreviousRowFunctionComputedColumn
。