SQL Server - 正确分解付款

时间:2015-12-14 12:42:57

标签: sql sql-server

这是我遇到的问题

示例:

  • 总价值:£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)

2 个答案:

答案 0 :(得分:6)

您只需要执行类似

的操作
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 :(得分:1)

我假设你有一个数字列表。其次,根据我的经验,之前的付款将被向上四舍五入,最终付款将低于该付款(您的标题是“正确”执行此操作):

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
     )