如何在SQL Server中获取累计和

时间:2019-07-10 12:09:31

标签: sql-server

我是这里的新手,我需要您的帮助,我有一个包含发票清单的数据,我想检查每张发票是否已付款。

这是我的数据

ID     | JO | C. ID  | L |Invoice |Amount |Payment 
279810 | B1 | CL0001 | a | FA0001 | 55638 | 170000
279812 | B1 | CL0001 | a | FA0002 | 40720 | 170000
279814 | B1 | CL0001 | a | FA0003 | 76644 | 170000
279868 | B1 | CL0001 | a | FA0004 | 51500 | 170000

这是我想要的结果:

ID     | JO | C. ID  | L |Invoice |Amount |Payment |Rest   | State
279810 | B1 | CL0001 | a | FA0001 | 55638 | 170000 | 0     | PAID
279812 | B1 | CL0001 | a | FA0002 | 40720 | 170000 | 0     | PAID
279814 | B1 | CL0001 | a | FA0003 | 76644 | 170000 | 3002  | P. PAYMENT
279868 | B1 | CL0001 | a | FA0004 | 51500 | 170000 | 51500 | NOT PAID

谢谢。

3 个答案:

答案 0 :(得分:1)

要获取累积发票金额,请使用sum(Amount) over (order by ID)。我假设它的顺序为ID。您还需要按客户划分。我没有将其包含在查询中,因为不确定该列的名称是什么

其余部分并不难理解。它使用CASE语句来确定它是已付款还是部分付款或未付款

select  *,
        Rest    = case  when    Payment > sum(Amount) over (order by ID)
                        then    0
                        when    sum(Amount) over (order by ID) - Payment < Amount
                        then    sum(Amount) over (order by ID) - Payment
                        else    Amount
                        end,
        State   = case  when    Payment > sum(Amount) over (order by ID)
                        then    'PAID'
                        when    sum(Amount) over (order by ID) - Payment < Amount
                        then    'P. PAYMENT'
                        else    'NOT PAID'
                        end

答案 1 :(得分:0)

对一个客户来说效果很好,但是如果我有多个客户,则计算是错误的。

这就是我得到的:

ID     | JO |Customer| L |Invoice |Amount |Payment |Rest   | State
-------+----+--------+---+--------+-------+--------+-------+-------------
279810 | B1 | CL0001 | a | FA0001 | 55638 | 170000 | 0     | PAID
279812 | B1 | CL0001 | a | FA0002 | 40720 | 170000 | 0     | PAID
279814 | B1 | CL0001 | a | FA0003 | 76644 | 170000 | 3002  | P. PAYMENT
279868 | B1 | CL0001 | a | FA0004 | 51500 | 170000 | 51500 | NOT PAID
279870 | B1 | CL0002 | a | FA0005 | 10000 | 60000  | 10000 | NOT PAID
279871 | B1 | CL0002 | a | FA0006 | 15000 | 60000  | 15000 | NOT PAID
279872 | B1 | CL0002 | a | FA0007 | 30000 | 60000  | 30000 | NOT PAID
279873 | B1 | CL0002 | a | FA0008 | 25000 | 60000  | 25000 | NOT PAID

这就是我应该得到的:

ID     | JO |Customer| L |Invoice |Amount |Payment |Rest   | State
-------+----+--------+---+--------+-------+--------+-------+-------------
279810 | B1 | CL0001 | a | FA0001 | 55638 | 170000 | 0     | PAID
279812 | B1 | CL0001 | a | FA0002 | 40720 | 170000 | 0     | PAID
279814 | B1 | CL0001 | a | FA0003 | 76644 | 170000 | 3002  | P. PAYMENT
279868 | B1 | CL0001 | a | FA0004 | 51500 | 170000 | 51500 | NOT PAID
279870 | B1 | CL0002 | a | FA0005 | 10000 | 60000  | 0     | PAID
279871 | B1 | CL0002 | a | FA0006 | 15000 | 60000  | 0     | PAID
279872 | B1 | CL0002 | a | FA0007 | 30000 | 60000  | 0     | PAID
279873 | B1 | CL0002 | a | FA0008 | 25000 | 60000  | 20000 | P. PAYMENT

答案 2 :(得分:0)

这个问题很有趣,因为在某些情况下可能没有部分付款,下面的查询应该可以满足您的要求:

CREATE TABLE #temp (ID INT,JO VARCHAR(10),CID VARCHAR(10),L VARCHAR(10), Invoice VARCHAR(10), Amount NUMERIC(10,2), Payment NUMERIC(10,2))
INSERT INTO #temp VALUES
(279810,'B1','CL0001','a','FA0001',55638,170000),
(279812,'B1','CL0001','a','FA0002',40720,170000),
(279814,'B1','CL0001','a','FA0003',73642,170000),
(279868,'B1','CL0001','a','FA0004',51500,170000),
(279868,'B1','CL0001','a','FA0004',200,170000),
(279868,'B1','CL0001','a','FA0004',1234678,170000),
(279868,'B1','CL0001','a','FA0004',90,170000),
(279870,'B1','CL0002','a','FA0005',10000,60000),
(279871,'B1','CL0002','a','FA0006',15000,60000),
(279872,'B1','CL0002','a','FA0007',30000,60000),
(279873,'B1','CL0002','a','FA0008',25000,60000)

SELECT ID,JO,CID,L,Invoice,Amount,Payment
    ,CASE WHEN t.[Balance] >=0 THEN 0 
          WHEN t.[Balance] <0 AND LAG(t.[Balance]) OVER( ORDER BY (SELECT 1)) > 0 THEN ABS(t.[Balance])
          ELSE [Amount] END AS [Balance Amount]
    ,CASE WHEN t.[Balance] >=0 THEN 'Paid'
          WHEN t.[Balance] <0 AND LAG(t.[Balance]) OVER( ORDER BY (SELECT 1)) > 0 THEN 'Partial Payment'
          ELSE 'Not Paid' END AS [Status]
FROM (
    SELECT *
        ,SUM(Amount) OVER (PARTITION BY CID ORDER BY (SELECT 1) ROWS UNBOUNDED PRECEDING ) Cumulative
    FROM #temp ) A
CROSS APPLY (VALUES(Payment - Cumulative)) AS T(Balance)

结果如下,

ID      JO  CID     L   Invoice  Amount     Payment     Balance Amount  Status
279810  B1  CL0001  a   FA0001   55638.00   170000.00   0.00            Paid
279812  B1  CL0001  a   FA0002   40720.00   170000.00   0.00            Paid
279814  B1  CL0001  a   FA0003   73642.00   170000.00   0.00            Paid
279868  B1  CL0001  a   FA0004   51500.00   170000.00   51500.00        Not Paid
279868  B1  CL0001  a   FA0004   200.00     170000.00   200.00          Not Paid
279868  B1  CL0001  a   FA0004   1234678.00 170000.00   1234678.00      Not Paid
279868  B1  CL0001  a   FA0004   90.00      170000.00   90.00           Not Paid
279870  B1  CL0002  a   FA0005   10000.00   60000.00    0.00            Paid
279871  B1  CL0002  a   FA0006   15000.00   60000.00    0.00            Paid
279872  B1  CL0002  a   FA0007   30000.00   60000.00    0.00            Paid
279873  B1  CL0002  a   FA0008   25000.00   60000.00    20000.00        Partial Payment