Create Table #Invoices
(
InvoiceID int,
Amount money,
ProjectID int
)
insert into #Invoices
(
InvoiceID,
Amount,
ProjectID
)
select
1,
100,
1
union all
select
2,
100,
2
union all
select
3,
100,
3
union all
select
4,
100,
4
Create Table #Projects
(
ProjectID int,
AccountCode int
)
insert into #Projects
(
ProjectID,
AccountCode
)
select
1,
'12345'
union all
select
2,
'12345'
union all
select
2,
'7890'
union all
select
3,
'800'
union all
select
3,
'234'
union all
select
3,
'987'
union all
select
4,
'800'
union all
select
4,
'234'
union all
select
4,
'987'
union all
select
4,
'2579'
This is a follow-on question from this one from a few years ago Split 1 row into 2 rows with % of total
I have the above sample data, and what I'm trying to do is split the Invoice rows into multiple rows based off the AccountCode, but calculate a split, so if there are 2 related AccountCodes, the Amount should be split 50%/50%, if there are 3, then split 33.3%/33.3%/33.3%, but one line being 34 so it evens out to the total. And so on and so forth.
This is a query I've put together so far:
select
I.*,
P.AccountCode,
I.Amount / count(I.InvoiceID) over (partition by P.ProjectID) as SplitAmount
from
#Invoices I
Inner Join #Projects P on
I.ProjectID = P.ProjectID
order by
I.InvoiceID
It seems to work in terms of the SplitAmount, but there is an issue. InvoiceID 3 contains three values of 33.33 which equals 99.99. How can I ensure the split will always equal the total amount regardless of the number of splits it has to?
Here is a table showing the end result I'm after. I've changed one of the rows to 33.34 so I get the 100 result, but bare in mind, the amount could be of any amount.
InvoiceID | Amount | ProjectID | AccountCode | SplitAmount |
---|---|---|---|---|
1 | 100.00 | 1 | 12345 | 100.00 |
2 | 100.00 | 2 | 12345 | 50.00 |
2 | 100.00 | 2 | 7890 | 50.00 |
3 | 100.00 | 3 | 800 | 33.33 |
3 | 100.00 | 3 | 234 | 33.33 |
3 | 100.00 | 3 | 987 | 33.34 |
4 | 100.00 | 4 | 800 | 25.00 |
4 | 100.00 | 4 | 234 | 25.00 |
4 | 100.00 | 4 | 987 | 25.00 |
4 | 100.00 | 4 | 2579 | 25.00 |
Sum up the SplitAmount
and verify with the #Invoices.Amount
and adjust any difference to one of the row.
You might want to round()
to 2 decimal places when calculating the SplitAmount
select *,
SplitAmount
+ case when rn = 1
then i.Amount - sum (i.SplitAmount)
over (partition by i.ProjectID)
else 0
end as AdjustedSplitAmount
from
(
select
I.*,
P.AccountCode,
round(I.Amount / count(I.InvoiceID) over (partition by P.ProjectID), 2) as SplitAmount,
-- for identifying one of row for adjustment
row_number() over (partition by P.ProjectID order by p.AccountCode) as rn
from
#Invoices I
Inner Join #Projects P on
I.ProjectID = P.ProjectID
) i