【问题标题】:SQL - Calculate row value based on previous row values for multiple entities at onceSQL - 一次根据多个实体的先前行值计算行值
【发布时间】:2016-09-26 22:56:25
【问题描述】:

我有以下情况:我有一份属于许多投资的交易清单。交易记录包含投资标识符、日期和总金额,但不包含运行余额。

交易表:

+------------+------------+--------+
| Investment | Date       | Gross  |
+------------+------------+--------+
| A          | 2015-01-01 |   +200 |
| B          | 2015-06-30 |   +500 |
| C          | 2016-01-10 |   +300 |
| A          | 2016-08-15 |   +100 |
| A          | 2016-09-21 |   -300 |
+------------+------------+--------+

余额存储在单独的表中,并且始终是最新的:

平衡表:

+------------+------------+
| Investment | Balance    |
+------------+------------+
| A          |          0 |
| B          |        500 |
| C          |        300 |
+------------+------------+

我想做的是获得每笔交易的运行余额,以及一次到某个特定点的所有投资。

例如,如果我想显示从 2016 年 1 月 1 日到 2016 年 8 月 31 日的投资 A、B 和 C 的交易,并且有流动余额,我会得到:

结果:

+------------+------------+--------+-------------+
| Investment | Date       | Gross  | End Balance |
+------------+------------+--------+-------------+
| C          | 2016-01-10 |    300 |         300 |
| A          | 2016-08-15 |    100 |         300 |
+------------+------------+--------+-------------+

我希望在没有迭代器的情况下理想地执行此操作,因为我认为它效率低下。此外,最好使用余额表并从当前余额向后工作,因为当我通常只需要显示一些和最近的交易时,一项投资可能有许多交易。

非常感谢您的帮助。

【问题讨论】:

  • in Result 你是如何得到 A 的期末余额的?
  • @Kostya 我做了当前余额减去所有交易的总价值:所以,0 - (-300) = 300

标签: sql sql-server iterator


【解决方案1】:

使用 CROSS APPLY 获取运行余额

SELECT t.Investment, t.Date, t.Gross, b.Balance
FROM   Transaction t
       CROSS APPLY
       (
           SELECT balance = SUM(x.Gross)
           FROM   Transaction x
           WHERE  x.Invenstment = t.Investment
           AND    x.Date <= t.Date
       ) b
WHERE  t.Date >= '2016-01-01'
AND    t.Date <= '2016-08-31'

编辑:处理多个相同日期的跨性别

; with Trans as
(
    SELECT *, rn = row_number() over (partition by Investment order by Date)
    FROM   Transaction
)
SELECT t.Investment, t.Date, t.Gross, b.Balance
FROM   Trans t
       CROSS APPLY
       (
           SELECT balance = SUM(x.Gross)
           FROM   Trans x
           WHERE  x.Invenstment = t.Investment
           AND    x.rn <= t.rn
       ) b
WHERE  t.Date >= '2016-01-01'
AND    t.Date <= '2016-08-31'

【讨论】:

  • 谢谢@Squirrel。这个解决方案让我:SELECT t.Investment, t.Date, t.Gross, b.balance FROM Transaction t OUTER APPLY (SELECT balance = (Current_Balance - sum(t2.Gross)) FROM Balance x INNER JOIN Transaction t2 on t2 .Investment = x.Investment WHERE x.Investment = t.Investment AND t2.Date > t.Date GROUP BY x.Current_Balance ) b WHERE t.Date >= '2016-01-01' AND t.Date
  • @KJY。编辑查询
【解决方案2】:

如果您使用的是 SQL 2012 或更高版本,请尝试以下查询。

   ;with cte_1
    AS (SELECT    Investment,Date
                 ,Gross
                 ,SUM(Gross) OVER(Partition by Investment ORDER BY Date
 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) EndBalance
                ,ROW_NUMBER()OVER(Partition By Investment Order By Date DESC)RNO
            FROM Transaction 
         WHERE Date between @starDate AND @endDate
         )

    SELECT     *
    FROM cte_1 A
    WHERE RNO =1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多