无法编写精确的sql查询来获取结果集

时间:2017-01-20 09:49:26

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

我有以下数据集类型:

Base    Col1    Col2    Col3
1000    0        10     1100
1100    0        10     1210
1210    0        10     1331

为了得到col3,我将使用像

这样的公式
col3 = (base - col1) * (1 + col2 / 100)

如果你观察到上面的数据集,col3值的第一行是第二行基列值。并且所有记录的Col2值都相同。

所以现在我的问题是在以后的时间我的col1(Col1列是公式的一部分)行值将基于此更新我需要使用提到的公式重新计算col3值。

参见下面的数据集,例如,如果col1值有更新,那么我们需要使用公式重新计算col3值(Col3 =(base-col1)*(1 + col2 / 100))

Base    Col1    Col2    Col3
 1000    10      10     1089
 1089    20      10     1175.9
 1175.9  30      10     1293.4

为了获得以上数据集,我尝试过如下。

SELECT 
    col1, col2, 
    col3 - SUM(col1 * (Power((1 + COL2 / 100.00), RNO))) 
              OVER(ORDER BY RNO ROWS UNBOUNDED PRECEDING)
FROM
    (SELECT 
         row_number() OVER(ORDER BY col1) rno,
         *
     FROM   
         #TABLE1) A

但我没有得到正确的结果。

请使用以下脚本创建表格和填充数据。

CREATE TABLE #Table1
  (
     [col1] INT,
     [col2] INT,
     [col3] INT
  );

INSERT INTO #Table1
            ([col1],
             [col2],
             [col3])
VALUES      (10,10, 1100),
            (20,10,1210),
            (30,10,1331); 

注意: - 在我的示例中,基本值总是取决于前一行col3值。

请帮帮我。

2 个答案:

答案 0 :(得分:2)

您不应将计算结果存储在表格中。如您所见,这是多余的,可能导致错误的数据。你的桌子也没有订单。首先要做的是:给记录一个时间戳或一个数字。然后删除Col3和Base。 (当然,你必须拥有初始基值,所以要么保留基列并使所有值为null,除了第一个值或将值存储在其他地方或在查询中使用修复值。)

Rno   Col1   Col2
1     0      10 
2     0      10 
3     0      10 

要获得结果,您需要递归查询。以下查询将RNO视为相邻(具有不相邻的数字或日期,您必须首先使用row_number对您的行进行编号)。这里我只用1000作为基础。如果这是可变的,将它存储在某处并从那里取出。

with cte(rno, base, col1, col2, col3) as
(
  select rno, 1000 as base, col1, col2, (1000 - col1) * (1 + col2/100) as col3
  from mytable
  where rno = 1
  union all
  select m.rno, cte.col3 as base, m.col1, m.col2, (cte.col3 - m.col1) * (1 + m.col2/100)
  from mytable m
  join cte on m.rno = cte.rno + 1
)
select * from cte
order by rno;

您当然可以为此创建视图。

答案 1 :(得分:0)

col1更改时,您需要更新同一行的col3
col3更改时,您需要更新下一行的Base
Base更改时,您需要更新同一行的col3 等等..

每次更新Basecol1col3都会运行此循环:

declare @i int = 1

while @i<>0 begin

    update t set Col3 = newCol3 
    from (
        select top 1 base, col1, col2, col3, (base - col1) * (1 + col2 / 100.0) newCol3
        from @t
        where col3 <> (base - col1) * (1 + col2 / 100.0) 
        order by base
    ) t

    update t set base = newbase
    from (
        select top 1 base, col1, col2, col3, newbase
        from (
            select base, col1, col2, col3, LAG(col3,1,null) over (order by base) newbase
            from @t 
        ) t
        where base <> newbase
        order by base
    ) t


    if @@ROWCOUNT=0 set @i=0
end

输出

base    col1    col2    col3
1000    10      10      1089
1089    20      10      1175,9
1175,9  30      10      1260,49 -- I think you have an error in your example