我需要计算数据库中的红利因子,一般方法所需的基本计算是row2 field2 = (row2's field1) * (row1's field2)
,其中field2
是我需要同时更新和查询的值,即我计算了一行,我需要该行前一行的计算值。
现在我有一个带有所有值的临时表,现在我需要计算最终值,但是当我尝试这个时:
UPDATE #temp SET field2 = IsNull( (SELECT d2.field2 * d.field1 FROM #temp AS d2 WHERE d2.rowNr = d.rowNr - 1) ,d.field1 ) FROM #temp as d ;
它始终看到field2
始终为NULL并且使用默认操作,它应该仅针对第一行。
现在目前我只知道两种方法:
但我仍然希望将其纳入单一声明,但我不知道如何做到这一点。我正在使用MS SQL 2008 R2。
修改
这是我正在使用的实际数据:(注意,在计算之前所有field2值都为NULL且数据类型为 money )
field1 field2(expected values) ------ ---------------------- 1,033 1,033 1,0363 1,0705 1,0558 1,1302 1,0157 1,1479 1,0188 1,1695 1,026 1,1999 1,0286 1,2342 1,0323 1,2741 1,0319 1,3147
答案 0 :(得分:2)
好的,如果我理解这一点,你想找到基于之前计算过的field2行的field2,这样你就需要某种形式的循环或递归。试试这个递归解决方案:
self
IF OBJECT_ID('tempdb..#temp') IS NOT NULL
DROP TABLE #temp;
DECLARE @yourTable TABLE (ID INT,field1 INT, field2 INT);
INSERT INTO @yourTable(ID,field1,field2)
VALUES (1111,11,11),(2222,22,22),(3333,33,33);
SELECT ROW_NUMBER() OVER (ORDER BY ID) rowNr,
ID,
field1,
field2 INTO #temp
FROM @yourTable;
WITH cte_recursion
AS
(
SELECT TOP 1
rowNR,
ID,
field1,
field2,
field1 AS dividend_factor
FROM #temp A
ORDER BY rowNr
UNION ALL
SELECT B.rowNr,
B.ID,
B.field1,
B.field2,
B.field1 * A.dividend_factor
FROM cte_recursion A
INNER JOIN #temp B
ON A.rowNr = B.rowNr - 1
)
结果:
UPDATE @yourTable
SET field2 = B.dividend_factor
FROM @yourTable A
INNER JOIN cte_recursion B
ON A.ID = B.ID
OPTION (MAXRECURSION 0)
SELECT *
FROM @yourTable
就我个人而言,我不会使用此更新,因为您必须不断确保数据更新到目前为止。我更倾向于使用我用来计算值的CTE并将其放在视图中,以便您知道值始终是最新的,并且您不必担心运行它。除非值已更新,否则实际表中的dividend_factor列将为NULL,否则为NULL。只是我的两美分
答案 1 :(得分:1)
UPDATE d1
SET d1.field2 = IsNull(d2.field2 * d1.field1, d1.field1)
FROM #temp AS d1
left outer join #temp AS d2
on d2.rowNr = d1.rowNr - 1
魔术
select d1.field1, EXP(SUM(LOG(d2.field1)))
from #temp AS d1
join #temp AS d2
on d2.rowNr <= d1.rowNr
group by d1.field1
op声称错误答案
为自己考试
drop table #temp;
create table #temp (ID int, val money);
insert into #temp (ID, val) values
(1, 1.033)
, (2, 1.0363)
, (3, 1.0558)
, (4, 1.0157)
, (5, 1.0188)
, (6, 1.026)
, (7, 1.0286)
, (8, 1.0323)
, (9, 1.0319);
SELECT TOP 10 [t1].[ID], EXP(SUM(LOG([t2].[val])))
from #temp AS t1
join #temp AS t2
on t2.[ID] <= t1.[ID]
group by t1.[ID]
order by t1.[ID]