SQL Server sharing cash with priority to creditors in sql

ih99xse1  于 2023-10-15  发布在  其他
关注(0)|答案(3)|浏览(78)

I have a table in sql 2014 with name "tblPaymentPlan" like this:

Creditors    PlanToPay      َAmount
----------------------------------
A            2017-01-20     2000
A            2017-02-20     1500
A            2017-03-20     3000
B            2017-01-25     3000
B            2017-02-25     1000

and also another table with name "tblPaid" like following:

Creditors    Paid      َ
-----------------
A            4500
B            3500

and the result that I expect:

Creditors    PlanToPay      َRemain
----------------------------------
A            2017-01-20     0
A            2017-02-20     0
A            2017-03-20     2000
B            2017-01-25     0
B            2017-02-25     500

I have no idea for doing this job at all! Would you please to help me to perform this job. Please informed that I have a lot of records in my tables. I need this query for budget planing. (We can use numbers for defining priority instead of dates)

j8yoct9x

j8yoct9x1#

What you want is a running total of what is owing, from that you can subtract what has been paid.

SELECT Creditors, PlanToPay, IIF(ABS(Remain)!=Remain,0,IIF(Remain<Amount,Remain,Amount)) as Remain
FROM (SELECT pp.Creditors, pp.PlanToPay, pp.Amount,
  SUM(pp.Amount) OVER(PARTITION BY pp.Creditors ORDER BY pp.PlanToPay ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)-tp.paid AS Remain
  FROM tblPaymentPlan pp 
  JOIN (SELECT creditors, sum(paid) as paid from tblpaid group by creditors) tp
  ON pp.creditors = tp.creditors) ss
ORDER By Creditors, PlanToPay

SQLFiddle

In the windowing function ( SUM OVER ) the PARTITION separates the creditors, the ORDER determines how the rows are arranged (by date), and the ROWS clause tells it to use all the rows in the partition before this row and include this row in the running total. We then subtract the sum of everything paid to that creditor from this running total.

This of course gives us alot of negative numbers, so we do it in a subquery. The main query checks if the absolute value of that remaining is equal to the value, true if it's positive, false if it is not, and returns the value remaining if true, or 0 if not.

UPDATE - added handling for multiple rows with value still owing

4dc9hkyq

4dc9hkyq2#

You can subtract the running total from amount in paid table and if it is less than 0, set remain to 0 else the difference of amount from the running total.

select pp.creditors,pp.plantopay,
case when sum(pp.amount) over(partition by pp.creditors order by pp.plantopay)-coalesce(pd.paid,0) <= 0 then 0
else sum(pp.amount) over(partition by pp.creditors order by pp.plantopay)-coalesce(pd.paid,0) end as remain
from tblpaymentplan pp
left join tblPaid pd on pp.creditors=pd.creditors
n3schb8v

n3schb8v3#

CREATE TABLE OM_FLIGHT FLIGHT_ID -- PK FLIGHT_CODE -- MUST BE 4 ALPHA NUMERIC FLIGHT_FROM -- MUST BE DFW or LAG FLIGHT_DATE -- MUST BE 2021-02-02 TO 2021-03-09 FLIGHT_DETINATION -- MUST BE ONLY CITY WHOSE NAME START WITH A, R, M

相关问题