SQL, What is the total amount each client has paid us? - sql

I've got a little problem here: I've created 5 tables: Customer, Invoice, Line, Product and Vendor.
Task asks me:
What is the total amount each client has paid us?
And the following comment:
To find the total amount each client has paid us you need to join
customer table with invoice and line. Group by customer code, sum
price from line. Balance would only show whether client owes us money.
Also when you perform a SUM there should also be a group by statement.
I've made a code, but stuck, because got confused:
SELECT Invoice.CUS_CODE
FROM Invoice
INNER JOIN Customer ON Invoice.CUS_CODE = Customer.CUS_CODE
WHERE Invoice.INV_NUMBER IN (
SELECT SUM(Line.LINE_PRICE)
FROM Line
INNER JOIN Invoice ON Invoice.INV_NUMBER = Line.INV_NUMBER
GROUP BY LINE_PRICE)
GROUP BY Invoice.CUS_CODE;
So, I need to group INV_NUMBER from Invoice table by CUS_CODE (customer code) from Customer and sum the LINE_PRICE of grouped INV_NUMBER. In the end group by CUS_CODE.
Thank You in advance.
UPD: Tables
Customer table
Line table
Invoice table

It seems that you are up to simple LEFT JOIN with GROUP BY
SELECT CUS_CODE, CUS_LNAME, CUS_FNAME, SUM(Line.LINE_PRICE)
FROM Customer
LEFT JOIN Invoice ON Invoice.CUS_CODE = Customer.CUS_CODE
LEFT JOIN Line ON Invoice.INV_NUMBER = Line.INV_NUMBER
GROUP BY CUS_CODE, CUS_LNAME, CUS_FNAME

Related

Getting only the last customer purchase

I have to write a query to get the following result: "We want to give a coupon with a 10% value of the last customer purchase. The customers eligible for this coupon must have made another purchase before the last one that is equal or bigger than the last one. Create a query that returns the coupon values for each one of the eligible customers."
I have the following query already written, who returns to me all the purchases and then the coupons' values, but for the result to be right I need only the rows matching the last customer purchase to be shown. Any idea on how to do this?
SELECT * FROM(
select *,
lag(PaymentValue) over (PARTITION BY IDCustomer ORDER BY ApprovalDate) LastPurchaseValue,
PaymentValue*0.1 as CouponValue
from (
SELECT Customers.customer_unique_id as IDCustomer,
Orders.order_id as IDOrder,
order_approved_at as ApprovalDate,
SUM(Payments.payment_value) as PaymentValue
from olist_customers_dataset as Customers
inner join olist_orders_dataset as Orders on Customers.customer_id = Orders.customer_id
INNER JOIN olist_order_payments_dataset as Payments on Payments.order_id = Orders.order_id
GROUP BY IDCustomer, IDOrder, ApprovalDate
ORDER BY IDCustomer
)
) WHERE LastPurchaseValue > PaymentValue
Here you can find the schema:

How to apply two where condition one inside subquery and the other out of subquery?

Find the customer that spend less than 3$ on individual film rentals, but has spent a total higher than 15?
The query that I wrote is given below
SELECT CustomerID,Customer.CustomerFirstName,Customer.CustomerSurname,Total FROM (SELECT DISTINCT Customer.CustomerID,Customer.CustomerFirstName,Customer.CustomerSurname,sum(([Rental].[Quantity])*([Film].[FilmPrice])) AS Total
FROM Film RIGHT JOIN (Customer INNER JOIN Rental ON Customer.CustomerID = Rental.CustomerIDFk) ON Film.FilmID = Rental.FlimIDFk
GROUP BY Customer.CustomerID,Customer.CustomerFirstName,Customer.CustomerSurname) T WHERE Total>15;
Now how can I apply the second condition which is FilmPrice<3
Please help me out.
This is the ERD
Thanks
Simply add another where clause inside the subquery, after your join on but before the group by for WHERE FilmPrice<3
You want to find the customers where the maximum price of a film they have rented is less than 3 and the total price of all the films they have rented is greater than 15.
Something like this:
SELECT CustomerID,
CustomerFirstName,
CustomerSurname
FROM Customer
WHERE CustomerId IN (
SELECT r.CustomerIDFk
FROM Rental r
INNER JOIN Film f
ON ( f.FilmId = e.FilmIdFk )
GROUP BY r.CustomerIdFk
HAVING MAX(f.FilmPrice) < 3
AND SUM(f.FilmPrice * r.Quantity)>15
)

Sql query to return information about customers which has spent the most amount

I have a database about the shop, and I need to return full information of the first 5 customers, which has spent the most amount, and in returned results also display that total amount. (counting all
his/her payments together from the payments table). Order descending by the total amount.
Can someone help with the query for this?
Customers Table
Payments Table
It should be something like this. You might have to play around but it will give you a good start.
SELECT c.CustomerName, SUM(p.amount) AS Total
FROM CustomersTable c
INNER JOIN PaymentsTable p
ON c.customerNumber = p.customerNumber
GROUP BY p.customerNumber DESC LIMIT 5
SELECT min(c.Customername), SUM(p.amount) AS Total
FROM Customers c
INNER JOIN payments p
on c.Customernumber=p.Customernumber
GROUP BY p.Customernumber
order by 2 DESC

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, GROUP BY on three tables to get totals

I've inherited the following DB design. Tables are:
customers
---------
customerid
customernumber
invoices
--------
invoiceid
amount
invoicepayments
---------------
invoicepaymentid
invoiceid
paymentid
payments
--------
paymentid
customerid
amount
My query needs to return invoiceid, the invoice amount (in the invoices table), and the amount due (invoice amount minus any payments that have been made towards the invoice) for a given customernumber. A customer may have multiple invoices.
The following query gives me duplicate records when multiple payments are made to an invoice:
SELECT i.invoiceid, i.amount, i.amount - p.amount AS amountdue
FROM invoices i
LEFT JOIN invoicepayments ip ON i.invoiceid = ip.invoiceid
LEFT JOIN payments p ON ip.paymentid = p.paymentid
LEFT JOIN customers c ON p.customerid = c.customerid
WHERE c.customernumber = '100'
How can I solve this?
I am not sure I got you but this might be what you are looking for:
SELECT i.invoiceid, sum(case when i.amount is not null then i.amount else 0 end), sum(case when i.amount is not null then i.amount else 0 end) - sum(case when p.amount is not null then p.amount else 0 end) AS amountdue
FROM invoices i
LEFT JOIN invoicepayments ip ON i.invoiceid = ip.invoiceid
LEFT JOIN payments p ON ip.paymentid = p.paymentid
LEFT JOIN customers c ON p.customerid = c.customerid
WHERE c.customernumber = '100'
GROUP BY i.invoiceid
This would get you the amounts sums in case there are multiple payment rows for each invoice
Thank you very much for the replies!
Saggi Malachi, that query unfortunately sums the invoice amount in cases where there is more than one payment. Say there are two payments to a $39 invoice of $18 and $12. So rather than ending up with a result that looks like:
1 39.00 9.00
You'll end up with:
1 78.00 48.00
Charles Bretana, in the course of trimming my query down to the simplest possible query I (stupidly) omitted an additional table, customerinvoices, which provides a link between customers and invoices. This can be used to see invoices for which payments haven't made.
After much struggling, I think that the following query returns what I need it to:
SELECT DISTINCT i.invoiceid, i.amount, ISNULL(i.amount - p.amount, i.amount) AS amountdue
FROM invoices i
LEFT JOIN invoicepayments ip ON i.invoiceid = ip.invoiceid
LEFT JOIN customerinvoices ci ON i.invoiceid = ci.invoiceid
LEFT JOIN (
SELECT invoiceid, SUM(p.amount) amount
FROM invoicepayments ip
LEFT JOIN payments p ON ip.paymentid = p.paymentid
GROUP BY ip.invoiceid
) p
ON p.invoiceid = ip.invoiceid
LEFT JOIN payments p2 ON ip.paymentid = p2.paymentid
LEFT JOIN customers c ON ci.customerid = c.customerid
WHERE c.customernumber='100'
Would you guys concur?
I have a tip for those, who want to get various aggregated values from the same table.
Lets say I have table with users and table with points the users acquire. So the connection between them is 1:N (one user, many points records).
Now in the table 'points' I also store the information about for what did the user get the points (login, clicking a banner etc.). And I want to list all users ordered by SUM(points) AND then by SUM(points WHERE type = x). That is to say ordered by all the points user has and then by points the user got for a specific action (eg. login).
The SQL would be:
SELECT SUM(points.points) AS points_all, SUM(points.points * (points.type = 7)) AS points_login
FROM user
LEFT JOIN points ON user.id = points.user_id
GROUP BY user.id
The beauty of this is in the SUM(points.points * (points.type = 7)) where the inner parenthesis evaluates to either 0 or 1 thus multiplying the given points value by 0 or 1, depending on wheteher it equals to the the type of points we want.
First of all, shouldn't there be a CustomerId in the Invoices table? As it is, You can't perform this query for Invoices that have no payments on them as yet. If there are no payments on an invoice, that invoice will not even show up in the ouput of the query, even though it's an outer join...
Also, When a customer makes a payment, how do you know what Invoice to attach it to ? If the only way is by the InvoiceId on the stub that arrives with the payment, then you are (perhaps inappropriately) associating Invoices with the customer that paid them, rather than with the customer that ordered them... . (Sometimes an invoice can be paid by someone other than the customer who ordered the services)
I know this is late, but it does answer your original question.
/*Read the comments the same way that SQL runs the query
1) FROM
2) GROUP
3) SELECT
4) My final notes at the bottom
*/
SELECT
list.invoiceid
, cust.customernumber
, MAX(list.inv_amount) AS invoice_amount/* we select the max because it will be the same for each payment to that invoice (presumably invoice amounts do not vary based on payment) */
, MAX(list.inv_amount) - SUM(list.pay_amount) AS [amount_due]
FROM
Customers AS cust
INNER JOIN
Payments AS pay
ON
pay.customerid = cust.customerid
INNER JOIN ( /* generate a list of payment_ids, their amounts, and the totals of the invoices they billed to*/
SELECT
inpay.paymentid AS paymentid
, inv.invoiceid AS invoiceid
, inv.amount AS inv_amount
, pay.amount AS pay_amount
FROM
InvoicePayments AS inpay
INNER JOIN
Invoices AS inv
ON inv.invoiceid = inpay.invoiceid
INNER JOIN
Payments AS pay
ON pay.paymentid = inpay.paymentid
) AS list
ON
list.paymentid = pay.paymentid
/* so at this point my result set would look like:
-- All my customers (crossed by) every paymentid they are associated to (I'll call this A)
-- Every invoice payment and its association to: its own ammount, the total invoice ammount, its own paymentid (what I call list)
-- Filter out all records in A that do not have a paymentid matching in (list)
-- we filter the result because there may be payments that did not go towards invoices!
*/
GROUP BY
/* we want a record line for each customer and invoice ( or basically each invoice but i believe this makes more sense logically */
cust.customernumber
, list.invoiceid
/*
-- we can improve this query by only hitting the Payments table once by moving it inside of our list subquery,
-- but this is what made sense to me when I was planning.
-- Hopefully it makes it clearer how the thought process works to leave it in there
-- as several people have already pointed out, the data structure of the DB prevents us from looking at customers with invoices that have no payments towards them.
*/