Select sum and inner join - sql

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

Related

Showing customers who have purchased more than 1 product, but from the same subscription

I'm trying to find the number of customers who have ordered more than one product, with the same subscription.
I've first selected the count of the id_customer from customer. Then joined on subscription and order (on the correct keys). This was done so that I have all the data available to me from all 3 tables. Then grouped by the id_customer to get just the unique customers. And lastly filtered to have a fk_product (products a customer has) greater than 1.
SELECT COUNT(t1.id_customer)
FROM customer t1
INNER JOIN subscription t2 ON t1.id_customer = t2.fk_customer
INNER JOIN order t3 ON t2.id_subscription = t3.fk_subscription
GROUP BY t1.id_customer
HAVING COUNT(t3.fk_product) > 1
I'd like to better understand if this is the correct syntax to obtain the data I'm looking for. Since I have t2.id_subscription and t3.fk_subscription linked, wouldn't this be correct? I'm still getting the wrong output. I'm thinking its perhaps the way I have my scopes, or some subtle aspect of SQL that I'm not using/understanding.
Thank you for your help!!
Use two levels of aggregation. Your data model is a bit hard to follow, but I think:
SELECT COUNT(DISTINCT so.fk_customer)
FROM (SELECT s.fk_customer, s.id_subscription
FROM subscription s
order o
ON s.id_subscription = o.fk_subscription
GROUP BY s.fk_customer, s.id_subscription
HAVING MIN(o.fk_product) <> MAX(o.fk_product)
) so
select count(distinct s.id_customer)
from (
SELECT t1.id_customer
FROM customer t1
INNER JOIN subscription t2 ON t1.id_customer = t2.fk_customer
INNER JOIN order t3 ON t2.id_subscription = t3.fk_subscription
GROUP BY t1.id_customer, t3.fk_subscription
HAVING COUNT(1) > 1
) s

Loop Query in Access

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.

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 Sum returning wrong number

I am adding up the amount of tickets sold for a sporting event, the answer should be under 100 but my answer is in the thousands.
SELECT Stubhub.Active.Opponent,
SUM(Stubhub.Active.Qty) AS AQty, SUM(Stubhub.Sold.Qty) AS SQty
FROM Stubhub.Active INNER JOIN
Stubhub.Sold ON Stubhub.Active.Opponent = Stubhub.Sold.Opponent
GROUP BY Stubhub.Active.Opponent
This is type of problem occurs because you are getting a cartesian product between each table for each opponent. The solution is to pre-aggregate by opponent:
SELECT a.Opponent, a.AQty, s.SQty
FROM (SELECT a.Opponent, SUM(a.Qty) as AQty
FROM Stubhub.Active a
GROUP BY a.Opponent
) a INNER JOIN
(SELECT s.Opponent, SUM(s.QTY) as SQty
FROM Stubhub.Sold s
GROUP BY s.Opponent
) s
ON a.Opponent = s.Opponent;
Notice that in this case, you do not need the aggregation in the outer query.

Get SUMs for dimension record from several fact tables

I have to 2 queries below which calculate to correct value:
Select Finances.CustomerID,
sum(Finances.Total)Total
from Finances
group by Finances.CustomerID
order by Finances.CustomerID
Select Invoices.CustomerID,
sum(Invoices.InvoiceValue)InvoiceValue
from Invoices
group by Invoices.CustomerID
order by Invoices.CustomerID
within the Finances table a customer can owe money from multiple orders, so for this example lets say the customer has to pay £100+ £400 + £500, which totals to £1000.
the customer then receives the 1st invoice for £100, and pays this..
so the 2nd query would now display £100.... from these 2 values I then want to calculate a 3rd column which deducts the £100 away from the £1000 equalling £900 (the amount left to pay)
the is my table structure:
there are a lot more tables associated however this is where I am the data from with the select statements :)
how would i write the sql statement to do this all together or is it not possible? ideally i would like the to be used within a INSERT -> SELECT -> WHERE NOT EXISTS Statement or alternatively populated in a view. thanks for the help
SAMPLE DATA:
CREATE VIEW CustomerFinances AS
;WITH FinancesCTE AS
(
Select Finances.CustomerID,
sum(Finances.Total)Total
from Finances
group by Finances.CustomerID
),InvoicesCTE AS
(
Select Invoices.CustomerID,
sum(Invoices.InvoiceValue)InvoiceValue
from Invoices
group by Invoices.CustomerID
)
SELECT C.*,
F.Total AS FinanceTotal,
I.InvoiceValue
FROM Customers C
LEFT JOIN FinancesCTE F
ON C.CustomerID = F.CustomerID
LEFT JOIN InvoicesCTE I
ON C.CustomerID = I.CustomerID
GO
Try this,
CREATE VIEW CustomerFinanceDetails AS
(
select c.*,isnull(FinanceTotal,0) as FinanceTotal,isnull(InvoiceTotal,0) as InvoiceTotal
from
(select * from Customers) c
left outer join
(select CustomerID,isnull(SUM(Total),0) as FinanceTotal from Finances group by CustomerID) f on c.CustumerID=f.CustomerID
left outer join
(select CustomerID,isnull(SUM(InvoiceValue),0) as InvoiceTotal from Invoices group by CustomerID) i on c.CustumerID= i.CustomerID
)