sql join query for multiple tables - sql

I have following tables structure,
cust_info:
cust_id cust_name
1 nikhil
2 sam
bill_info:
bill_id cust_id bill_amount
7 1 10000
8 1 15000
9 2 6000
10 2 4000
paid_info:
paid_id cust_id paid_amount
11 1 5000
12 1 5000
13 2 5000
14 2 5000
now my output should display sum of bill made by customer and total amount paid by that customer and balance amount
output
cust_id total_bill total_paid balance
1 25000 10000 15000
2 10000 10000 0
where,
for example,
for cust_id = 2,
total_bill= 10000 + 15000
total_paid = 5000 + 5000
balance = total_bill - total_paid
what is convenient way to do this in sql? any sample query?
here's what i've already tried
SELECT distinct c.cust_id
, sum(b.bill_amount) as total_bill
, SUM(p.paid_amt) AS totalpaid,sum(b.bill_amount) - SUM(p.paid_amt) AS balance
FROM cust_info c
INNER JOIN bill_info b ON c.cust_id = b.cust_id
INNER JOIN paid_info p ON p.cust_id= b.cust_id group by p.cust_id;

SELECT
cust_info.cust_id,
cust_name,
bill_amount,
paid_amount,
bill_amount - paid_amount AS balance
FROM cust_info
INNER JOIN (
SELECT cust_id, SUM(bill_amount) bill_amount
FROM bill_info
GROUP BY cust_id
) bill_info ON bill_info.cust_id = cust_info.cust_id
INNER JOIN (
SELECT cust_id, SUM(paid_amount) paid_amount
FROM paid_info
GROUP BY cust_id
) paid_info ON paid_info.cust_id = cust_info.cust_id
demo

SELECT c.cust_id,
SUM(b.total_bill),
SUM(p.total_paid),
SUM(c.total_bill) - SUM(p.total_paid)
FROM
cust_info c
LEFT JOIN bill_info b ON (c.cust_id = b.cust_id)
LEFT JOIN paid_info p ON (c.cust_id = p.party_id)
GROUP
BY cust_info.cust_id

SELECT DISTINCT cust_info.cust_id,
sum(bill_amount) AS 'total_bill' ,
sum(paid_amount) AS 'total paid' ,
(SUM(bill_amount) - sum(paid_amount)) AS balance
FROM cust_info
INNER JOIN bill_info ON cust_info.cust_id = bill_info.cust_id
INNER JOIN paid_info ON cust_info.cust_id = paid_info.cust_id
GROUP BY cust_info.cust_id

Related

sql join on join

transactions table (1 row --> 1 transaction)
customer_code amount
A0BEFG 100
DEC21A 80
payment table (1 row --> 1 transaction)
customer_id payment_type
1 cash
2 credit_card
customer table (1 row --> 1 customer_code)
customer_code customer_id
A0BEFG 2
DEC21A 1
Expected output:
combined table
customer_code customer_id amount payment_type
AOBEFG 2 100 credit_card
DEC21A 1 80 cash
In words, my idea is to get the payment_type into the transactions table, but because there is no matching variable, I need to first merge payment table and customer table, before connecting them to the transactions table.
Code I've tried:
with
connection as (
select c.customer_code, c.customer_id, p. payment_type
from data.payment p
left join data.customer c on p.customer_id = c.customer_id
),
transactions as (
select t.merchant_code, t.amount
from data.transactions t
)
select
t.merchant_code, c.customer_id, c.amount, p.payment_type
from transactions as t
Code is for PostgreSQL.
SELECT c.customer_code, c.customer_id, t.amount, p.payment_type
FROM customer AS c
INNER JOIN payment AS p ON p.customer_id = c.customer_id
INNER JOIN transactions AS t ON t.customer_code = c.customer_code
Join customer to the other tables like this:
SELECT c.customer_code, c.customer_id, t.amount, p.payment_type
FROM transactions t
INNER JOIN customer c ON t.customer_code = c.customer_code
INNER JOIN payment p ON p.customer_id = c.customer_id
See the demo.
Results:
customer_code
customer_id
amount
payment_type
A0BEFG
2
100
credit_card
DEC21A
1
80
cash

How to Sum previos rows summatory to find a balance in SQL Server

I'm working on a service that needs to calculate how much a customer owes, according to a total invoice value and the partial payments that the customer has made.
So, in a tableA I have a row with the invoice total value:
[dbo].[TableA]
ID CustomerId InvoiceVal
1 12 1000
2 11 2000
3 10 5000
4 14 15000
5 12 100
6 16 8000
7 18 3200
In a TableB I have the record of each customer's partial payments they have made to each invoice:
[dbo].[TableB]
ID InvoiceId Payment
1 1 150
2 3 50
3 1 120
4 1 100
5 5 90
6 4 7500
So, as you can see, the customer 12 has an invoice for $1000 and has made 3 payment that sum $370
I need to be able to se the partial total owed in each row, this is the expected result:
No. InoviceId CustomerId Payment Owed
1 1 12 150 850
2 1 12 120 730
3 1 12 100 630
So far, this is my code:
DECLARE #invid int = '1'
DECLARE #invoicetotal numeric(18,2)
SET #invoicetotal =
(
SELECT
[dbo].[TableA].[InvoiceVal]
FROM [dbo].[TableA]
WHERE
([dbo].[TableA].[ID] = #invid)
)
SELECT
*,
SUM(#invoicetotal - [dbo].[TableB].[Payment]) OVER(ORDER BY [dbo].[TableB].[ID] ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS [Owed]
FROM [dbo].[TableB]
WHERE
([dbo].[TableB].[InvoiceId] = #invid)
But this is what I get:
ID InvoiceId Payment Owed
1 1 150.00 NULL
3 1 120.00 850.00
4 1 100.00 1730.00
I need to sum the previous payment on each row.
Thanks!
Something like this would help
SELECT
ROW_NUMBER() OVER (ORDER BY TableB.ID ASC) NO,
CustomerId,
Payment,
InvoiceVal - SUM(Payment) OVER (PARTITION BY TableA.ID ORDER BY TableB.Id ASC) Owed
FROM TableA
INNER JOIN TableB
ON TableA.Id = TableB.InvoiceId
WHERE
CustomerId = 12
Working Fiddle
Your query will depend on what you are trying to make as your final output.
If you want just ONE CustomerID, go with:
SELECT a.ID AS InvoiceID, a.CustomerID, a.InvoiceVal AS StartInvoice
, b.ID AS bid, b.Payment
, a.InvoiceVal - ISNULL(SUM(b.Payment) OVER (PARTITION BY a.ID ORDER BY b.id),0) AS owed
FROM TableA a
LEFT OUTER JOIN TableB b ON a.ID = b.InvoiceID
WHERE a.CustomerID = 12
And if that CustomerID doesn't have any payments, you want to use a LEFT JOIN so that you don't eliminate an amount owed.
SELECT a.ID AS aid, a.CustomerID, a.InvoiceVal AS StartInvoice
, b.ID AS bid, b.Payment
, a.InvoiceVal - ISNULL(SUM(b.Payment) OVER (PARTITION BY a.ID ORDER BY b.id),0) AS owed
FROM TableA a
LEFT OUTER JOIN TableB b ON a.ID = b.InvoiceID
WHERE a.CustomerID = 11
I also added an ISNULL() around Payment to keep from nulling out your owed amount. It could also be added to the InvoiceVal to account for a CustomerID who hasn't been invoiced yet, if that was needed (or possible from other tables).
IF you want to get ALL CustomerIDs, you'll have to account for that in your partition.
SELECT s1.CustomerID, aid AS InvoiceID, s1.bid, s1.Payment
, (s1.StartInvoice - s1.runningPayment) AS Owed
FROM (
SELECT a.ID AS aid, a.CustomerID, a.InvoiceVal AS StartInvoice
, b.ID AS bid, b.Payment
, ISNULL(SUM(b.Payment) OVER (PARTITION BY a.CustomerID, a.ID ORDER BY b.id),0) AS runningPayment
FROM TableA a
LEFT OUTER JOIN TableB b ON a.ID = b.InvoiceID
) s1
ORDER BY s1.CustomerID, s1.aid, s1.bid
Fiddle demonstrates overpayment or paying total balance for 0 owed.

Calculate the sum of group in a table and joining on other table sql

i have two tables in sql.
table_team
t_id team_name
1 ABC
2 XYZ
3 PQR
i have another table_player
p_id t_id player_name payment
10 1 Sam 1000
20 1 jon 500
30 2 will 680
40 1 bob 700
50 3 rob 890
i want to get the team's total payment from these two tables.
i'e sum of payemnt of each player in a particular team, and for all teams.
i thought of trying
select t_id,team_name,sum(b.payment) as total_payment from table_team a
left join table_player b on a.t_id = b.t_id
Join to a subquery which computes the total payment for each team:
SELECT t1.t_id, t1.team_name, t2.total_payment
FROM table_team t1
INNER JOIN
(
SELECT t_id, SUM(payment) AS total_payment
FROM table_player
GROUP BY t_id
) t2
ON t1.t_id = t2.t_id
-- WHERE t1.team_name IN ('ABC', 'XYZ')
select t_id,team_name,sum(b.payment) as total_payment
from table_team a
left join table_player b on a.t_id = b.t_id
group by t_id,team_name
select t_id,team_name,sum(isnull(b.payment,0)) as total_payment from table_team a
left join table_player b on a.t_id = b.t_id
group by t_id, team_name
Just add a group by and it should work

Group By syntax while using Cross Join

i wish to apply a Group By condition to my SQL below so that the O/P will display POL# with GP.
select t.POl#, (DEB.CUSTD - CRED.CUSTC) AS GP
from (
(
select POL.SP_NUM POL#
, sum(D.AMT) AS CUSTD
from S_INVOICE D
, S_ASSET POL
where POL.ROW_ID = D.FN_ACCNT_ID
and POL.SP_NUM in ('000','111','222')
and D.DEBIT_TYPE = 'Customer'
group by POL.SP_NUM
) DEB
CROSS JOIN
(
select pol.SP_NUM POL#
, sum(C.AMT) AS CUSTC
from S_SRC_PAYMENT C
, S_ASSET POL
where POL.ROW_ID = C.ASSET_ID
and POL.SP_NUM in ('000','111','222')
and C.CG_DEDN_TYPE_CD = 'Customer'
group by POL.SP_NUM
) CRED
) t
group by t.POL#
When i execute the same I am getting "ORA-00933: SQL command not properly ended" error, where the cursor points to 't'
Kindly assist.
Expected O/P:
POL# GP
000 800
111 120
222 50
Appending Sample Data with explanation for better understanding of requirement:
Table 1:
S_ASSET
ROW_ID POL#
1 000
2 111
3 222
4 333
5 444
Table 2:
S_INVOICE (Debit Table)
FN_ACCNT_ID POL# DEBIT_TYPE AMT
1 000 Customer 10
1 000 Customer 10
1 000 Insurer 5
2 111 Customer 10
3 222 Customer 10
3 222 Insurer 5
5 444 Insurer 10
Table 3:
S_SRC_PAYMENT (Credit Table)
ASSET_ID POL# CG_DEDN_TYPE_CD AMT
1 000 Insurer 10
1 000 Insurer 10
1 000 Customer 5
2 111 Insurer 10
3 222 Insurer 5
3 222 Insurer 5
3 222 Customer 5
5 444 Customer 10
As per this query I will consider "Customer" records per POL# and SUM the AMT. (Every Debit for the Customer will Credit Insurer(s) per POL# & vice-versa)
Expected O/P (Sum of Debits - Sum of Credits) for a Customer per POL#
POL # AMT (GP)
000 15
111 10
222 5
333 0
444 -10
You obviously only want to get the deb and cred per s_asset and then aggregate so as to get the sums. You can do this without a join and subquery the sums directly instead:
select
sp_num as pol#,
sum(<get deb sum for the pol.row_id here>) - sum(<get cred sum for the pol.row_id here>)
from s_asset pol
where sp_num in ('000','111','222')
group by sp_num;
The complete query:
select
sp_num as pol#,
coalesce(sum(
(
select sum(deb.amt)
from s_invoice deb
where deb.fn_accnt_id = pol.row_id
and deb.debit_type = 'Customer'
)
), 0) -
coalesce(sum(
(
select sum(cred.amt)
from s_src_payment cred
where cred.asset_id = pol.row_id
and cred.cg_dedn_type_cd = 'Customer'
), 0)
) as gp
from s_asset pol
where sp_num in ('000','111','222')
group by sp_num;
The same with joins instead:
select
pol.sp_num as pol#,
coalesce(sum(deb.total), 0) - coalesce(sum(cred.total), 0) as gp
from s_asset pol
left join
(
select fn_accnt_id as pol_row_id, sum(deb.amt) as total
from s_invoice
where debit_type = 'Customer'
group by fn_accnt_id
) deb on deb.pol_row_id = pol.row_id
left join
(
select asset_id as pol_row_id, sum(amt) as total
from s_src_payment
where cg_dedn_type_cd = 'Customer'
group by asset_id
) cred on cred.pol_row_id = pol.row_id
group by pol.sp_num;
This syntax
from ( (select ...) CROSS JOIN (select ...) )
is invalid. A JOIN belongs to a FROM. So either of these would be correct:
from ( SELECT * FROM (select ...) CROSS JOIN (select ...) )
or
from (select ...) CROSS JOIN (select ...)
However, are you sure you want a CROSS JOIN at all? Both subqueries give you POL numbers plus data, bat rather than joining them on POL#, you cross join the results, so you get all POL# combinations instead.

MS Access SQL Query - Joining 3 Tables to receive Total Order Price

I would like to know the total price for a specific order ID. The information is contained in these tables:
Order_line_t
Order_ID Product_ID Quantity
-------- ---------- --------
1006 4 1
1006 5 2
1006 7 2
Uses_t
Product_ID Material_ID Footage
---------- ----------- -------
4 16 20
5 15 13
7 10 16
Raw_Materials_t
Material_ID Unit_Price
----------- ----------
16 05.70
15 16.72
10 15.55
The total cost is computed by
Multiplying SUM ( Order_line_t.Quantity * Uses_t.Footage * Raw_Materials_t.Unit_Price) AS Total
My current query only returns an error:
SELECT Order_line_t.Order_ID, Order_line_t.Product_ID, Uses_t.Product_ID ,Uses_t.Footage ,
SUM ( Order_line_t.Quantity * Uses_t.Footage * Raw_Materials_t.Unit_Price) AS Total
FROM Order_line_t, Uses_t , Raw_Materials_t
WHERE Order_line_t.Order_ID = 1006;
Help appreciated! How exactly do I JOIN these tables? What am i missing?
Firstly you were missing the actual joins between the tables, and secondly you were missing your group by
SELECT Order_line_t.Order_ID,
Order_line_t.Product_ID,
Uses_t.Product_ID ,
Uses_t.Footage ,
SUM ( Order_line_t.Quantity * Uses_t.Footage * Raw_Materials_t.Unit_Price) AS Total
FROM Order_line_t INNER JOIN
Uses_t ON Order_line_t.Product_ID = Uses_t.Product_ID INNER JOIN
Raw_Materials_t ON Uses_t.Material_ID = Raw_Materials_t.Material_ID
WHERE Order_line_t.Order_ID = 1006;
GROUP BY Order_line_t.Order_ID,
Order_line_t.Product_ID,
Uses_t.Product_ID ,
Uses_t.Footage
EDIT
Try this
SELECT Order_line_t.Order_ID,
Order_line_t.Product_ID,
Uses_t.Product_ID,
Uses_t.Footage,
Sum([Order_line_t].[Quantity]*[Uses_t].[Footage]*[Raw_Materials_t].[Unit_Price]) AS Total
FROM (Order_line_t INNER JOIN
Uses_t ON Order_line_t.Product_ID = Uses_t.Product_ID) INNER JOIN
Raw_Materials_t ON Uses_t.Material_ID = Raw_Materials_t.Material_ID
GROUP BY Order_line_t.Order_ID,
Order_line_t.Product_ID,
Uses_t.Product_ID,
Uses_t.Footage;
EDIT
Total by ORDER ID
SELECT Order_line_t.Order_ID,
Sum([Order_line_t].[Quantity]*[Uses_t].[Footage]*[Raw_Materials_t].[Unit_Price]) AS Total
FROM (Order_line_t INNER JOIN
Uses_t ON Order_line_t.Product_ID = Uses_t.Product_ID) INNER JOIN
Raw_Materials_t ON Uses_t.Material_ID = Raw_Materials_t.Material_ID
GROUP BY Order_line_t.Order_ID;
I think you need to compute the cost for each row, then sum the entire order. Something like:
select
Order_ID, sum(RowCost) as OrderCost
from (
select
o.Order_ID, o.Product_ID, o.Quantity,
u.Material_ID, u.Footage,
r.Unit_Price,
(o.Quantity * u.Footage * r.UnitPrice) as RowCost
from
order_line_t o INNER JOIN
uses_t u on o.Product_ID = u.Product_ID INNER JOIN
Raw_materials_t r on u.Material_ID = r.Material_ID
where
o.Order_ID = 1006
) z
group by
Order_ID