【问题标题】:Alternative to LAG() in SQL ServerSQL Server 中 LAG() 的替代方法
【发布时间】:2020-09-18 16:12:11
【问题描述】:

免责声明:SQL Server 编程中的新功能

我目前正在用 SQL 进行一个我无法计算的计算。

基本上,这是一个有期初余额的计算,一些计算取决于期初余额和期末余额。表格的最终结果应该如下:

| Employee  | ROWN |Balance_year1 | O_balance | calc   | C_balance |
--------------------------------------------------------------------
| Emp1      |  1   | 1000         | 1000      | 20     | 1020      |
| Emp1      |  2   | 1000         | 1020      | 20.4   | 1040.4    | 
| Emp1      |  3   | 1000         | 1040.4    | 20.808 | 1061.208  | 
| Emp2      |  1   | 2000         | 2000      | 40     | 2040      |
| Emp2      |  2   | 2000         | 2040      | 40,8   | 2080,8    |
| Emp2      |  3   | 2000         | 2080,8    | 41,616 | 2122,416  |

到目前为止,我写的代码如下:

WITH table1 AS (
    SELECT
       *
     , [O_balance] = LAG([C_balance], 1, [Balance_year1]) OVER (PARTITION BY [Employee] ORDER BY [ROWN] ASC)
    FROM dataset
),
table2 AS (
    SELECT 
       *
     , [calc]      = --Some calculations that depends on the [C_balance] from the row before
    FROM table1
)
SELECT 
    *
  , [O_balance]
  , [calc]
  , [C_balance] = [O_balance] + [calc]  
FROM table2

我对桌子的问题是:

  1. [C_balance]在第一个CTE使用时没有计算,所以不能运行。 (无效的列名[C_balance]
  2. [C_balance][calc] 中使用时计算不正确。

我想您可以逐行计算表格,也可以将 [C_balance] 保存在一个变量中,然后在整个运行过程中对其进行更新,但是 idk?

我希望你们中的一个可以帮助我 - 斗争是真实的 :-) 谢谢!

【问题讨论】:

  • [C_balance]中是否有列dataset
  • 不,我在*之后所做的所有列都是用于计算的添加列
  • 那么你对LAG([C_balance], 1, [Balance_year1])有什么期望?
  • 你有其他选择吗?我尝试了很多不同的东西,但我认为这个失败的例子是最好的,可以让你了解这个问题:-) 我可以告诉你,有些语言你可以看一个排成 peek-function i Qlik

标签: sql sql-server common-table-expression calculation cumulative-sum


【解决方案1】:

你可以用递归 CTE 做你想做的事:

with cte as (
      select employee, rown, balance, balance as o_balance, balance * 1.02 as c_balance
      from dataset
      where rown = 1
      union all
      select d.employee, d.rown, d.balance, cte.c_balance, cte.c_balance * 1.02
      from cte join
           dataset d
           on cte.employee = d.employee and d.rown = cte.rown + 1
    )
select *
from cte;

我在推测您的计算是什么,但这适用于您提供的数据。

【讨论】:

  • 感谢您的帮助 - 它确实帮助解决了我发布的问题。第一次尝试时我没有很好地解释安静(对不起-> 猜我是菜鸟)。你能检查我在表格中的变化吗?谢谢!
  • @xxxKryptoPiratenxxx 。 . .通常,你应该问一个新的问题。在这种情况下,我认为您实际上打算由员工执行此操作,并且修改相当简单,因此我更新了答案。
【解决方案2】:

对我来说,这看起来像是一个运行总和问题(并且问题被标记为这样,所以我将继续使用它)。一、代码:

with d as (
    select * from (values
        ('Emp1',  1   , 1000         , 1000      , 20     , 1020      ),
        ('Emp1',  2   , 1000         , 1020      , 20.4   , 1040.4    ), 
        ('Emp1',  3   , 1000         , 1040.4    , 20.808 , 1061.208  ), 
        ('Emp2',  1   , 2000         , 2000      , 40     , 2040      ),
        ('Emp2',  2   , 2000         , 2040      , 40.8   , 2080.8    ),
        ('Emp2',  3   , 2000         , 2080.8    , 41.616 , 2122.416  )
    ) as x(Employee  , ROWN ,Balance_year1 , O_balance , calc   , C_balance)
), c as (
    select *, balance_year1 + sum(calc) over (partition by employee order by rown) as myCalc
    from d
)
select *, C_balance - myCalc
from c

我在这里使用公用表表达式只是为了方便使用 - 第一个以可消费格式获取数据,第二个用于显示中间步骤。最后的查询表明我的计算和你的计算得出了相同的答案。 “魔法”是sum(calc) over (partition by employee order by rown) 位。在相当现代的 SQL 版本中(在 2012 年 iirc 中引入,但可能更早),您可以这样做以获得运行总和。

【讨论】:

    猜你喜欢
    • 2014-04-09
    • 2023-03-05
    • 2019-04-29
    • 2021-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-12
    相关资源
    最近更新 更多