【问题标题】:Unable to write exact sql query to get result set无法编写准确的 sql 查询来获取结果集
【发布时间】:2017-01-20 22:16:38
【问题描述】:

我有以下类型的数据集:

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=(base-col1)*(1+col2/100)) 重新计算 col3 值,如下所示

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 值。

请帮帮我。

【问题讨论】:

  • 如果 col3 中的值是实际计算的,并且应该与 col1 和 col2 中的值一起改变,为什么不使用computed column
  • @Shnugo 我认为计算列将不起作用,因为我的基列值总是会改变。这取决于上一行 col3。
  • 啊,我明白了,你正在重新发明 Excel :-) 开个玩笑:Thorsten Kettner 的第一句话是真的:你不应该将计算结果存储在你的表中(唯一的例外:实际性能问题)。
  • 你解决了吗?你找到有用的答案了吗?

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


【解决方案1】:

您不应将计算结果存储在表中。正如您所注意到的,这是多余的并且可能导致错误的数据。你的桌子也没有订单。所以第一件事:给记录一个时间戳或一个数字。然后删除 Col3 和 Base。 (当然,您必须具有初始基值,因此要么保留基列并将除第一个之外的所有值设为空值,要么将值存储在其他位置,或者在查询中使用固定值。)

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;

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

【讨论】:

    【解决方案2】:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-26
      • 1970-01-01
      • 1970-01-01
      • 2013-12-07
      • 1970-01-01
      • 2020-01-15
      • 2021-11-25
      • 2019-11-08
      相关资源
      最近更新 更多