Loop Query in Access - sql

I have two tables in Acces. The one shows all my accounts called ACCOUNTS (there are duplicates) and the second table shows all the transactions and is called TRANSACTIONS.
ACCOUNTS
TRANSACTIONS
I basically want to create a table showing all the unique account numbers and then the sum of all the debit transactions transaction for each account in one column and then the sum of all the credit transactions for each account in a second columns. Individually the queries will be something as follows:
SELECT DISTINCT(Account_Number) FROM ACCOUNTS
and then
SELECT SUM(Amount) from TRANSACTIONS GROUP BY Debit_Account INTO DEBIT and then SELECT SUM(Amount) from TRANSACTIONS GROUP BY Credit_Account INTO CREDIT
So ultimately you will have a table with the following headings
ACCOUNT
DEBIT
CREDIT
How would I combine the two queries. I am guessing it will be done via a FOR LOOP but not sure how to construct it in Access.
Any assistance will be greatly appreciated.

You seem to want left join and group by:
select a.account_number, sum(t.amount)
from accounts as a left join
transactions as t
on a.account_number = t.account
group by a.account_number;
If all the accounts have at least one transaction, then your second query is pretty much what you want:
SELECT Account, SUM(Amount)
FROM TRANSACTIONS
GROUP BY Account;
In my opinion, you should always include the GROUP BY keys in the SELECT of an aggregation query -- unless you have a really good reason for excluding them.
EDIT:
For your revised question, how about just using correlated subqueries:
select a.*,
(select sum(t.amount)
from transaction as t
where t.debit_account = a.account_number
) as debits,
(select sum(t.amount)
from transaction as t
where t.credit_account = a.account_number
) as credits
from account as a

This code answers the original question.
Join the 2 queries like this
SELECT a.Account_Number, a.Account_Name, t.Total
FROM (SELECT DISTINCT Account_Number, Account_Name FROM ACCOUNTS) AS a
INNER JOIN (SELECT Account, SUM(Amount) AS Total from TRANSACTIONS GROUP BY Account) AS t
ON t.Account = a.Account_Number
If you don't use the 1st query and instead you join the table ACCOUNTS then you will get wrong results because the sums will be multiplied by the number of duplicates in the table ACCOUNTS.

Related

Subquery amount not coming in full

I have this query:
Select I.Invoice_Number, PA.Invoice_Number, I.Line_Amount, PA.Invoiced_Amount
from XXX as PA
Left join (select Invoice_Number, Line_Amount from Invoices) as I
on PA.Invoice_Number = I.Invoice_Number
Group by PA.Invoice_Number;
Both should give me the same amount of cost (I.Line_Amount = PA.Invoice_Amount) per Invoice_Number, yet I.Line_Amount is only bringing the first row on the list, while PA.Invoiced.Number brings the sum of the cost on that Invoice.
I tried using sum(Line_Amount) within the subquery but all records come out as Null.
Is there a way for me to join both tables and make sure that the amounts per invoice match to the total amount of that invoice?
Thanks!!
If I understand you correctly (and you want to make sure that sum of Line_Amount in Invoices table is the same as Invoiced_Amount in XXX table) the second table should have invoice number and sum of amounts:
select I.Invoice_Number, PA.Invoice_Number, I.total, PA.Invoiced_Amount
from XXX as PA
left join (
select Invoice_Number, sum(Line_Amount) as total
from Invoices
group by Invoice_Number
) as I
on PA.Invoice_Number = I.Invoice_Number
You can try it here: http://sqlfiddle.com/#!9/d1d010/1/0

SQL JOIN AND SUB QUERY

below are two tables customer information and second customer with their loan and repayment I want to join these two tables and retrieve the expected result in the picture, please note that in the second table one customer can have more than one loan and he/she can repay it in several installments that in the second table that it saved in many rows, I am expecting to join the two tables and retrieve clients who are still owed from the company.
I found the expected result as a good solution for this purpose but could not retrieve the expected result.
and if you have a good solution for my purpose rather than expected result please share.
example:-
I tried below query but it does not work, because the client id number 1 disbursed three times loan when it shows the tree times purpose it shows that total of the loan three times too
SELECT DISTINCT
CUSTOMER_AIB_INFO_TABLE.ID,
CUSTOMER_AIB_INFO_TABLE.NAME,
(
SELECT SUM (CUSTOMER_AIB_LOAN_TABLE.LOAN) AS "Total Loan"
FROM CUSTOMER_AIB_LOAN_TABLE
WHERE CUSTOMER_AIB_INFO_TABLE.ID = CUSTOMER_AIB_LOAN_TABLE.FK_ID
) AS "Loan",
(
SELECT SUM (CUSTOMER_AIB_LOAN_TABLE.REPAYMENT) FROM CUSTOMER_AIB_LOAN_TABLE
WHERE CUSTOMER_AIB_INFO_TABLE.ID = CUSTOMER_AIB_LOAN_TABLE.FK_ID
) AS Repayment ,
CUSTOMER_AIB_LOAN_TABLE.PURPOSE
FROM CUSTOMER_AIB_INFO_TABLE
INNER JOIN CUSTOMER_AIB_LOAN_TABLE
ON CUSTOMER_AIB_INFO_TABLE.ID = CUSTOMER_AIB_LOAN_TABLE.FK_ID
Instead of Subquery you could use a inner join on select table group by id
SELECT DISTINCT
CUSTOMER_AIB_INFO_TABLE.ID,
CUSTOMER_AIB_INFO_TABLE.NAME,
T.Total_Loan AS "Loan",
T.Total_Rep AS Repayment,
CUSTOMER_AIB_LOAN_TABLE.PURPOSE
FROM CUSTOMER_AIB_INFO_TABLE
INNER JOIN (
SELECT CUSTOMER_AIB_LOAN_TABLE.FK_ID as FK_ID,
SUM (CUSTOMER_AIB_LOAN_TABLE.LOAN) AS Total_Loan
, SUM (CUSTOMER_AIB_LOAN_TABLE.REPAYMENT) AS Total_Rep
FROM CUSTOMER_AIB_LOAN_TABLE
GROUP BY CUSTOMER_AIB_LOAN_TABLE.ID
) T on t.FK_ID = CUSTOMER_AIB_INFO_TABLE.ID

Total amount of financing already provided to each customer

I have three separate tables:
SystemA_Cash
SystemA_Loans
SystemB_CarLoans
Each table has Cash_AdvanceID field, Customer, & Funded Amount.
I need to total the amount funded for each customer.
Each customer can be present in any of the tables too.
So far I did
SELECT SystemA_CashAdvances.CashAdvanceID, SystemA_CashAdvances.Customer,
SystemA_CashAdvances.Funded_Amount
FROM
SystemA_CashAdvances
INNER JOIN
SystemA_Loans ON SystemA_Loans.CashAdvanceID = SystemA_CashAdvances.Cash_AdvanceID
INNER JOIN
SytemB_CarLoans ON SystemA_CashAdvances.Cash_AdvanceID = SystemB_CarLoans.CashAdvanceID;
It doesn't seem to return one table with the customers and the total amount each was funded.
You can use UNION and GROUP BY for this, like:
SELECT Cash_AdvanceID,
Customer,
SUM(Funded_Amount) AS "Total_Funded_Amount"
FROM (
SELECT Cash_AdvanceID,
Customer,
Funded_Amount
FROM SystemA_CashAdvances
UNION
SELECT Cash_AdvanceID,
Customer,
Funded_Amount
FROM SystemA_Loans
UNION
SELECT Cash_AdvanceID,
Customer,
Funded_Amount
FROM SytemB_CarLoans
)
GROUP BY Cash_AdvanceID,
Customer;
To do this with JOIN will be hard, as MS Access does not support a full outer join, as other database engines do. The closest is a one-sided outer join, as follows:
SELECT a.Cash_AdvanceID,
a.Customer,
a.Funded_Amount + Nz(l.Funded_Amount)
+ Nz(c.Funded_Amount) AS "Total_Funded_Amount"
FROM (SystemA_CashAdvances AS a
LEFT JOIN SystemA_Loans AS l
ON a.Cash_AdvanceID = l.Cash_AdvanceID)
LEFT JOIN SytemB_CarLoans AS c
ON a.Cash_AdvanceID = c.Cash_AdvanceID;
The above will work for customers that appear at least in the table SystemA_CashAdvances. If they only appear in another table, they will be excluded from the result. To get those in as well, you would need to use UNION again, which brings us back to the first solution above.

Select sum and inner join

I have two tables
Bills: id amount reference
Transactions: id reference amount
The following SQL query
SELECT
*,
(SELECT SUM(amount)
FROM transactions
WHERE transactions.reference = bils.reference) AS paid
FROM bills
GROUP BY id HAVING paid<amount
was meant to some rows from table Bills, adding a column paid with the sum of amount of related transactions.
However, it only works when there is at least one transaction for each bill. Otherwise, no line for a transaction-less bill is returned.
Probably, that's because I should have done an inner join!
So I try the following:
SELECT
*,
(SELECT SUM(transactions.amount)
FROM transactions
INNER JOIN bills ON transactions.reference = bills.reference) AS paid
FROM bills
GROUP BY id
HAVING paid < amount
However, this returns the same value of paid for all rows! What am I doing wrong ?
Use a left join instead of a subquery:
select b.id, b.amount, b.paid, sum(t.amount) as transactionamount
from bills b
left join transactions t on t.reference = b.reference
group by b.id, b.amount, b.paid
having b.paid < b.amount
Edit:
To compare the sum of transactions to the amount, handle the null value that you get when there are no transactions:
having isnull(sum(t.amount), 0) < b.amount
You need a RIGHT JOIN to include all bill rows.
EDIT
So the final query will be
SELECT
*,
(SELECT SUM(transactions.amount)
FROM transactions
WHERE transactions.reference = bills.reference) AS paid
FROM bills
WHERE paid < amount
I knows this thread is old, but I came here today because I encountering the same problem.
Please see another post with same question:
Sum on a left join SQL
As the answer says, use GROUP BY on the left table. This way you get all the records out from left table, and it sums the corresponding rows from right table.
Try to use this:
SELECT
*,
SUM(transactions.sum)
FROM
bills
RIGHT JOIN
transactions
ON
bills.reference = transactions.reference
WHERE
transactions.sum > 0
GROUP BY
bills.id

SQL Query Help obtaining last order date from 2 tables

I have the following table
Orders_All
Account
Orders all contains every order line many thousand records and the 2 records are order_date and order_account_id.
This need to join into the Account so other queries can be run as well but I want a report that shows the account_id and the last order date but only one record per account.
How can I create a query to acgieve this.
SELECT account_id, MAX(order_date) as last_order_date FROM Orders_All INNER JOIN Account ON order_account_id = account_id GROUP BY account_id
That will give you the account ID and the maximum (furthest in the future) date. The GROUP BY is what limits it - it's the maximum date "for each" account_id.
If an account has no orders and you still want that account to show, with a NULL in the date column, use a RIGHT OUTER JOIN instead of INNER JOIN there.
Try this:
Select accound_id,Max(OrderDate) from Order_All t1,AccountID t2
where t1.AccountID = t2.AccountID
group by account_ID
Subtitute * for the columns you want to show or leave it and try the next code.
select distinct * from Account A
join Orders_All O on O.order_account_id = A.account_id
--so far we have join both table, so we need the last order date from it
where o.order_date in (select MAX(order_date) from Orders_All)
--in where clause im getting max order date from table Orders_All
but what if I want last order date by customer?
Well then you could write this (not the best but it works):
select *
from Account A
join (select account_id as Acc_id, MAX(order_date) as Date
from Orders_All
group by account_id)
as OD on A.account_id = OD.Acc_id