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

SQL Server 15.0.2070.41:计算成员应付Nits的总金额

解决SQL Server中分摊金额计算问题

看起来你遇到的核心问题是逗号分隔的分摊成员列需要拆分成独立行,再按成员汇总金额,而且要正确计算每个成员应付给Nits的净额。我来给你一步步拆解解决方案:

步骤1:理清需求逻辑

我们需要计算的是每个成员「欠Nits的净额」:

  • 当Nits是付款人时,每个分摊成员需要付给Nits自己的分摊份额(毕竟Nits已经垫付了总费用)
  • 当其他成员是付款人且Nits参与分摊时,Nits需要付给该成员分摊份额,这部分要从该成员欠Nits的金额中扣除

步骤2:用STRING_SPLIT拆分逗号分隔的成员

你的SQL Server版本是15.0(2019),刚好支持STRING_SPLIT函数。我们先把每个费用的分摊成员拆分成独立行,同时算出每人的分摊金额:

WITH SharedExpenses AS (
    SELECT
        ed.Name AS Payer,
        -- 去除成员名前后可能存在的空格,避免识别为不同成员
        LTRIM(RTRIM(s.value)) AS SharedMember,
        -- 转成DECIMAL避免整数除法丢失精度,保证金额准确
        CAST(ed.Price AS DECIMAL(18,2)) / ed.No_Of_Person AS ShareAmount
    FROM tb_Expense_Details ed
    CROSS APPLY STRING_SPLIT(ed.Name_Of_Person, ',') s
    -- 过滤无效的分摊人数,避免除以0报错
    WHERE ed.No_Of_Person > 0
)

步骤3:汇总每个成员应付给Nits的净额

接下来按成员分组,计算最终的应付金额:

  • 第一部分:Nits付款时,该成员所有分摊金额的总和
  • 第二部分:该成员付款时,Nits所有分摊金额的总和
  • 净额 = 第一部分 - 第二部分

完整SQL语句如下:

WITH SharedExpenses AS (
    SELECT
        ed.Name AS Payer,
        LTRIM(RTRIM(s.value)) AS SharedMember,
        CAST(ed.Price AS DECIMAL(18,2)) / ed.No_Of_Person AS ShareAmount
    FROM tb_Expense_Details ed
    CROSS APPLY STRING_SPLIT(ed.Name_Of_Person, ',') s
    WHERE ed.No_Of_Person > 0
)
SELECT
    sm.Member,
    -- 计算净额:该成员欠Nits的钱 减去 Nits欠该成员的钱
    COALESCE(SUM(CASE WHEN se.Payer = 'Nits' THEN se.ShareAmount ELSE 0 END), 0)
    - COALESCE(SUM(CASE WHEN se.SharedMember = 'Nits' AND se.Payer = sm.Member THEN se.ShareAmount ELSE 0 END), 0)
    AS AmountOwedToNits
FROM (
    -- 获取所有非Nits的成员列表(如果需要包含Nits自己,可去掉WHERE条件)
    SELECT DISTINCT LTRIM(RTRIM(s.value)) AS Member
    FROM tb_Expense_Details ed
    CROSS APPLY STRING_SPLIT(ed.Name_Of_Person, ',') s
    WHERE LTRIM(RTRIM(s.value)) <> 'Nits'
) sm
LEFT JOIN SharedExpenses se 
    ON sm.Member = se.SharedMember 
    OR (se.Payer = sm.Member AND se.SharedMember = 'Nits')
GROUP BY sm.Member
ORDER BY AmountOwedToNits DESC;

关键细节说明

  1. 去空格处理:LTRIM(RTRIM(s.value))避免因为逗号分隔时的空格导致成员名重复(比如"Nishant"和" Nishant"被误判为不同成员)
  2. 精度保证:用CAST(ed.Price AS DECIMAL(18,2))避免整数除法丢失小数部分
  3. NULL处理:COALESCE确保即使某个成员没有相关记录,也会返回0而不是NULL
  4. 成员去重:通过SELECT DISTINCT获取唯一的成员列表,从根源避免结果出现重复成员

执行这个语句后,你就能得到每个成员唯一、金额为分摊净额的结果,完全符合你想要的「Nishant付100、Nitish付125」这类预期输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 22:17:34