Reputation: 137
I'm experiencing some trouble comparing related data in different tables, I would be very grateful to get some assistance on the topic below. Unfortunately I'm not sure what the DBS is (nothing cutting edge though), but running it on IBM hardware. So to simplify the dataset:
INVOICES
Doci Sumi
1005 10
1006 15
1007 7
1008 20
PAYMENTS
Docp Sump
1006 -15
1005 -4
1005 -6
1007 -7
The aim is to compare two tables and see if there is a match - essentially if the invoice amount has been covered in the payments or not. The first new thing for me was to compare the numeric data which is in negative values in the other chart, but got it to work with the -1 multiplier.
The remaining issue that I can't really come up with a solution for is essentially making the query understand that record / invoice no 1005 is covered, just with two transactions. Essentially the result should only be invoice no 1008 as it does not have a match in the payment table.
I did end up reviewing SQL aggregate functions and namely SUM, however really didn't figure out how to utilize it as I don't want to summarize values in the entire Sump column, but only those that have a identical record in the Docp column.
So far what I have is this:
SELECT * from INVOICES
inner join PAYMENTS on INVOICES.Doci = PAYMENTS.Docp
where Sumi <> (Sump*-1)
So, this query works to the extent that I will not get records such as 1006 and 1007 in the result, but I do get 1005, as seemingly value 10 is compared to 4, instead of 4 + 6.
Many thanks in advance for any feedback!
Upvotes: 2
Views: 176
Reputation: 446
I did this in two steps? - had to group them together to identify if there was multiple payments, and whether it balanced the invoice or not:
SELECT doci, sumi, docp, sum(sump) as Sump INTO #Step1
from #INVOICES
inner join PAYMENTS on INVOICES.Doci = PAYMENTS.Docp
GROUP BY
doci, sumi, docp
GO
SELECT * from INVOICES
inner join #PAYMENTS on #INVOICES.Doci = #PAYMENTS.Docp
where Sumi <> (Sump*-1) AND doci NOT IN (select doci from #step1 WHERE sumi+Sump = 0)
Results are an empty dataset, as it will only return values where the payment was insufficient to cover the invoice (or too much!)
All the IDs in your example have a match (i.e. payments == invoice)
Upvotes: 0
Reputation: 3454
You need to break up the problem into steps:
First sum the payments by it's id, Docp.
select
Docp,
SUM(Sump) as payment_sum
from PAYMENTS
group by Docp
let's call the result of this query, PAYMENT_SUM.
Then compare it with invoice.
select
I.Doci,
I.sumi + P.payment_sum as diff
from INVOICES I
left join PAYMENT_SUM P
on I.Doci = P.Docp
;
This will give you a result as:
Doci diff
1005 0
1006 0
1007 0
1008 null
Now looking at this result, you can add one more clause to the query to select what you want. If you want to select invoice with no match at all on payment side, then clause will be
where P.Docp is null
Or, if you want to also have those invoices which has a match in payment but the amount is not fully covered, then:
where (P.Docp is null) or ((I.sumi + P.payment_sum) <> 0)
Now, to combine all the steps:
select
I.Doci,
I.sumi + P.payment_sum as diff
from INVOICES as I
left join (
select
Docp,
SUM(Sump) as payment_sum
from PAYMENTS
group by Docp
) as P
on I.Doci = P.Docp
where (P.Docp is null) or (I.sumi + P.payment_sum) <> 0
;
Upvotes: 0
Reputation: 1542
try this, it will give you only oustanding amount.
declare @inv table (Doci int, Sumi decimal)
insert @inv values (1005, 10), (1006, 15), (1007, 7), (1008, 20)
declare @pmt table (Docp int, Sump decimal)
insert @pmt values (1005, -4), (1006, -15), (1007, -7), (1005, -6)
;with payments(doc, amt)
as (
select Docp, sum(Sump)
from @pmt
group by Docp
)
select Doci, Sumi + isnull(amt,0) as Remaining
from @inv
left outer join payments p on p.doc = Doci
where (Sumi + isnull(amt,0)) <> 0
result:
Doci Remaining
----------- ----------
1008 20
Upvotes: 0
Reputation: 39497
You can find total sump of each docp and then join it with the invoices table based on doc and sum
select i.* from invoices i
inner join (
select
docp,
sum(sump) sump
from payments
group by docp
) p on i.doci = p.docp
and i.sumi + p.sump <> 0
Upvotes: 1