You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server中如何累加历史行求和计算客户欠款余额

解决发票分期付款剩余欠款计算问题

我来帮你搞定这个计算剩余欠款的问题!你的核心需求是针对每笔分期付款,实时展示发票的剩余欠款,当前代码的逻辑偏差导致了错误结果,我们来一步步修正它。

问题分析

你当前的代码错误在于窗口函数的计算逻辑:你试图累加(发票总额 - 单笔付款),这会导致数值越算越大,完全偏离了“剩余欠款”的实际含义。正确的逻辑应该是:

剩余欠款 = 发票总额 - 截至当前的累计付款金额

我们需要先计算每笔付款的累计总和,再用发票总额减去这个累计值,就能得到当前行的剩余欠款。

修正后的代码(针对单个发票)

如果你只需要计算指定发票的欠款,可以用这个版本,完全贴合你最初的变量设定:

DECLARE @invid int = 1;
DECLARE @invoicetotal numeric(18,2);

SET @invoicetotal = (
    SELECT InvoiceVal
    FROM [dbo].[TableA]
    WHERE ID = @invid
);

SELECT
    ROW_NUMBER() OVER(ORDER BY [dbo].[TableB].[ID]) AS [No.],
    [dbo].[TableB].[InvoiceId],
    (SELECT CustomerId FROM [dbo].[TableA] WHERE ID = @invid) AS CustomerId,
    [dbo].[TableB].[Payment],
    @invoicetotal - SUM([dbo].[TableB].[Payment]) OVER(ORDER BY [dbo].[TableB].[ID] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS [Owed]
FROM [dbo].[TableB]
WHERE [dbo].[TableB].[InvoiceId] = @invid;

代码说明

  1. 用SUM([dbo].[TableB].[Payment]) OVER(...)计算截至当前行的累计付款金额,ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW确保包含当前行的付款。
  2. 用发票总额减去累计付款,得到实时剩余欠款。
  3. ROW_NUMBER()生成你预期的序号列No.。

通用版本(处理所有发票)

如果需要一次性计算所有发票的每笔付款欠款,可以直接关联两张表,不需要单独声明变量:

SELECT
    ROW_NUMBER() OVER(PARTITION BY tb.InvoiceId ORDER BY tb.ID) AS [No.],
    tb.InvoiceId,
    ta.CustomerId,
    tb.Payment,
    ta.InvoiceVal - SUM(tb.Payment) OVER(PARTITION BY tb.InvoiceId ORDER BY tb.ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS [Owed]
FROM [dbo].[TableB] tb
JOIN [dbo].[TableA] ta ON tb.InvoiceId = ta.ID
ORDER BY tb.InvoiceId, tb.ID;

代码说明

  1. PARTITION BY tb.InvoiceId按发票分组,确保每个发票单独计算累计付款。
  2. 直接通过JOIN关联TableA和TableB,获取发票总额和客户ID,无需额外子查询。

验证结果

针对你提到的客户12的发票ID1,运行代码后会得到完全符合预期的结果:

No.InvoiceIdCustomerIdPaymentOwed
1112150850
2112120730
3112100630

内容的提问来源于stack exchange,提问作者epaezr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:09:39