【问题标题】:SQL Server - break down a payment correctlySQL Server - 正确分解付款
【发布时间】:2015-12-14 12:42:57
【问题描述】:

这是我遇到的问题

示例:

  • 总价值:1550.00 英镑
  • 每月付款 12

这计算在 129.16666666666666667,但是你不会显示这样的货币价值,它会显示为 129.17 英镑,等于 1550.04 英镑,这是错误的

问题

是否可以从 12 个分期付款中的 11 个中删除浮动/小数值,并仅在第一次或最后一次付款中显示?

示例结果

    PaymentNumber         Value
          1              £129.00 
          2              £129.00 
          3              £129.00 
          4              £129.00 
          5              £129.00 
          6              £129.00 
          7              £129.00 
          8              £129.00 
          9              £129.00 
         10              £129.00 
         11              £129.00 
         12              £131.00

感谢您的帮助,如果有任何关于我可以做到这一点的其他方法的建议,我将不胜感激..

我已经包含了我用来测试这个表的代码......并且还添加到了下面的数据中。现在使用更新语句是可以接受的,我会在以后尝试使代码更高效。我确实有一个程序正在运行,它以编程方式插入每月的细分。

我正在使用的表格信息

CREATE TABLE CustomerFinance (CustomerFinanceID int identity (1,1) not null,
TotalValueOwed decimal(12,4), --1550.00
LengthOfContract int) --LENGTGH IN MONTHS, i.e. 12

CREATE TABLE CustomerFinanceLine (CustomerFinanceLineID int identity (1,1) not null,
CustomerFinanceID int, --FOREIGN KEY LINK
PaymentNumber int, --1, 2, 3 AND SO ON
PaymentValue decimal(12,4)) --THE MONTHLY BREAKDOWN COSTS

--KEYS
alter table CustomerFinance add constraint CustomerFinanceID_PK PRIMARY KEY (CustomerFinanceID)
alter table CustomerFinanceLine add constraint CustomerFinanceLineID_PK PRIMARY KEY (CustomerFinanceLineID)
alter table CustomerFinanceLine add constraint CustomerFinanceID_FK FOREIGN KEY (CustomerFinanceID) REFERENCES CustomerFinance(CustomerFinanceID)

--PaymentNumber COUNTER (RUNS IN A PROCEDURE)
CREATE PROCEDURE FinanceCounter AS
;WITH MyCTE AS
(
    SELECT *,
           ROW_NUMBER() OVER(PARTITION BY CustomerFinanceID ORDER BY CustomerFinanceLineID) AS NewVariation
    FROM   CustomerFinanceLine
)
UPDATE MyCTE 
SET    PaymentNumber = NewVariation
WHERE PaymentNumber IS NULL

数据

--inserted PaymentValue as null for now, ideally i will
-- have a procedure to do this and insert the breakdowns programmatically
--for now an update statement will do fine unless its easier to insert it
INSERT INTO CustomerFinance VALUES (1550.00, 12)

INSERT INTO CustomerFinanceLine VALUES (1, 1, NULL)
INSERT INTO CustomerFinanceLine VALUES (1, 2, NULL)
INSERT INTO CustomerFinanceLine VALUES (1, 3, NULL)
INSERT INTO CustomerFinanceLine VALUES (1, 4, NULL)
INSERT INTO CustomerFinanceLine VALUES (1, 5, NULL)
INSERT INTO CustomerFinanceLine VALUES (1, 6, NULL)
INSERT INTO CustomerFinanceLine VALUES (1, 7, NULL)
INSERT INTO CustomerFinanceLine VALUES (1, 8, NULL)
INSERT INTO CustomerFinanceLine VALUES (1, 9, NULL)
INSERT INTO CustomerFinanceLine VALUES (1, 10, NULL)
INSERT INTO CustomerFinanceLine VALUES (1, 11, NULL)
INSERT INTO CustomerFinanceLine VALUES (1, 12, NULL)

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    你只需要做类似的事情

    WITH T(PaymentNumber) AS
    (
    SELECT 1 UNION ALL
    SELECT 2 UNION ALL
    SELECT 3 UNION ALL
    SELECT 4 UNION ALL
    SELECT 5 UNION ALL
    SELECT 6 UNION ALL
    SELECT 7 UNION ALL
    SELECT 8 UNION ALL
    SELECT 9 UNION ALL
    SELECT 10 UNION ALL
    SELECT 11 UNION ALL
    SELECT 12
    )
    SELECT CASE WHEN PaymentNumber < 12 THEN FLOOR(1550.00/12)
              WHEN PaymentNumber = 12 THEN 1550.00 - 11*FLOOR(1550.00/12)
           END
    FROM T
    

    【讨论】:

    • 是否需要选择 1-12?因为我可能包括 18 个月、24 个月的故障等?
    • @Crezzer7 - 您可以改用永久号码表。或者只是计算定期付款和最终付款的两个值,然后在您的应用程序中调用它。我对您现有的表或您使用此结果集的上下文一无所知。
    • 我在上面为您添加了一些上下文...我已经尝试过了,但是在将表格信息应用到其中时遇到问题,例如用 CustomerFinance.TotalValueOwed 替换 1550.00
    • 从您的底部声明中找到了一种解决方法,非常感谢
    【解决方案2】:

    假设您有一个数字列表。其次,根据我的经验,较早的付款会被四舍五入向上,最后的付款会少于该付款(您的标题“正确”地这样做了):

    select n.n as PaymentNumber,
           (case when n.n < @NumPayments then ceiling(@Amount / @NumPayments)
                 else @Amount - @NumPayments * ceiling(@Amount / @NumPayments)
            end) as MonthlyAmount
    from numbers n
    where n.n <= @NumPayments;
    

    当然,您可以使用FLOOR() 做同样的事情。注意:这可能需要少量调整。

    编辑:

    n.n 只是数字。您可以使用CTE。这是一个例子:

    with numbers as (
          select 1 as n
          union all
          select n + 1
          from numbers
          where n < 20
         )
    

    【讨论】:

    • n.n 是什么意思?
    • 每月汇总是个坏主意。简单示例:总共取 13 美元。 这导致每月支付 2 美元,而在 12 月,您需要要求返还 11 美元;)
    • @SQLOTL 。 . .根据我的经验,这个问题询问了正确的方法,最后一次付款通常少于之前的付款。小额金额不会使用四舍五入到完整的货币单位。
    • @GordonLinoff 算法应该是通用的。我的经验是:有一天你摔倒了异常并且你遇到了问题。例如,这种支付算法可能用于预算数据库,并且金额被分配到多个成本中心。瞧:你的钱很少。
    • @SQLOTL 。 . .我重复。根据我的经验,最后一次付款少于 次付款。有一些方法可以使方法“通用”,但增加的复杂性似乎对这个问题来说是不必要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-30
    • 2023-03-13
    • 2015-04-28
    • 2020-01-03
    • 1970-01-01
    • 2015-01-19
    • 2020-11-04
    相关资源
    最近更新 更多