I have three tables customer, customer_account, account_transaction
Table structure is as follow -
Customer
Id,
Branch,
Name
..
customer_account
Id,
Cust_id,
Loanamout,
EMI
account_transaction
ID,
account_id,
amount,
date
I need to get branch wise details in form of count of Loan given, sum of loan given, and sum of emi received for a particular branch. below is my current query -
SELECT
count(s.id) as cntloan,
SUM(s.Loanamout)
(
SELECT SUM(amount)
FROM account_transaction i
WHERE s.id = i.account_id
) AS curbal
From
customer as c,
customer_account as s
where c.branch = 1 and s.cust_id = c.id
It is giving me desired result for count of loan and sum of loan given. but not giving the right sum of EMI paid by customers
Can anyone help me on this.
Thanks you very much
This SQL has aggregative functions such as count and sum, so without a group by, this would not work.
SELECT customer.id,
COUNT(customer_account.id) as cntloadn,
SUM(customer_account.loan) as loan,
SUM(account_transaction.amount)
FROM customer
JOIN customer_account ON customer_account.cust_id = customer.id
JOIN account_transaction ON account_transaction.account_id = customer_account.id
GROUP BY customer.id
Related
I'm trying to create a query to find what is the total amount owed by each customer to the company. It is the GROUP BY customerNumber in the sub query that is creating the problem.
SELECT customerName,
customers.customerNumber,
SUM(quantityOrdered * priceEach) - ( SELECT SUM(amount) AS MoneyPayed FROM payments GROUP BY customerNumber ) AS AmountOwed
FROM payments
INNER JOIN customers ON payments.customerNumber = customers.customerNumber
INNER JOIN orders ON customers.customerNumber = orders.customerNumber
INNER JOIN orderdetails ON orders.orderNumber = orderdetails.orderNumber
GROUP BY customerNumber;
The tables I'm trying to link are payments and orderdetails.
When I get rid of the GROUP BY I get results in negatives as the total SUM of amount is subtracted from each row of SUM(quantityOrdered * priceEach).
How can I change this so that I can return multiple rows from payments to subtract from SUM(quantityOrdered * priceEach) from the order details table.
Link to DB as StackOverflow doesn't allow me to post images
Thanks for help, sorry if format is bad, this is my first post.
You will need a couple of subqueries to meet your requirement. Let us break it down.
First, you need the total value of orders from each customer. You're very close to the correct query for that. It should be
SELECT orders.customerNumber,
SUM(orderdetails.quantityOrdered * orderdetails.priceEach) owed
FROM orders
JOIN orderdetails ON orders.orderNumber = orderdetails.orderNumber
GROUP BY orders.customerNumber
This subquery's result set gives customerNumber and owed, the amount owed. Notice that orders::orderdetails is a one::many relationship, so we're sure we're counting each detail just once, so the SUMs will be correct.
Next we need the amount paid by each customer. This subquery is fairly simple.
SELECT customerNumber,
SUM(amount) paid
FROM payments
GROUP BY customerNumber
Now for the operation you're missing in your question: we need to join these two subqueries to your customers table.
SELECT customers.customerName, customers.customerNumber
owed.owed - paid.paid balance
FROM customers
LEFT JOIN (
SELECT orders.customerNumber,
SUM(orderdetails.quantityOrdered * orderdetails.priceEach) owed
FROM orders
JOIN orderdetails ON orders.orderNumber = orderdetails.orderNumber
GROUP BY orders.customerNumber
) paid ON customers.customerNumber = paid.customerNumber
LEFT JOIN (
SELECT customerNumber,
SUM(amount) paid
FROM payments
GROUP BY customerNumber
) owed ON customers.customerNumber = owed.customerNumber
See how this works? We join a table and two subqueries. Each subquery has either zero or one rows for each row in the table, so we need not use SUMs or GROUP BY in the outer query.
There's only one complication left: what if a customer has never paid anything? Then the value of paid.paid will be NULL after the LEFT JOIN operation. That will force the value of owed - paid to be NULL. So we need more smarts in the SELECT statement to yield correct sums.
SELECT customers.customerName, customers.customerNumber
COALESCE(owed.owed,0) - COALESCE(paid.paid,0) balance
...
COALESCE(a,b) is equivalent to if a is not null then a else b.
Pro tip In queries or subqueries with JOIN operations, always mention table.column instead of just column. The next person to work on your query will thank you.
can someone assist with the following. I need to figure out what the average day difference is between the first and second purchase of a customer:
I have the below: can someone assist with with my query please.
SELECT src.id, AVG(DATEDIFF(dest.purchasing, src.registrations)) AS avgdays FROM
(SELECT accounts.id, accounts.`created_date` AS registrations FROM accounts
WHERE YEAR(accounts.`created_date`) =2018 AND MONTH(accounts.`created_date`) =4) src
INNER JOIN
(SELECT account_id, MIN(created_date) AS purchasing
FROM ordering
WHERE STATUS = 'Fulfilled'
GROUP BY account_id
) dest
ON
dest.account_id = src.id;
The below query will give you the average difference between 2nd purchase if customer registration date is also his first order purchase date.
select account_id,customer_created,
avg(DATEDIFF(order_created, customer_created)) from
(select a.account_id,b.created_at as order_created, a.created_at
customer_created from
(select * from accounts where YEAR(created_at) =2018 AND
MONTH(created_at) =4) a
INNER JOIN ordering b on a.account_id=b.account_id where
b.status="Delivered" ) a
where customer_created <> order_created GROUP BY a.account_id ;
Why is an inner join necessary necessary when all info is located in ONE table? Explain please. just getting hang of joins.
If you were interviewing for an entry level analyst job (which I am), given the following sample query and table description, what other observations/questions would you have on this information?
Table: sales_data
**Field** **Description**
date Date of order|
customer_id Unique ID for Customers|
brand Unique ID for the brand of a purchased item|
quantity Quantity of item purchased|
amount Item Price
select customer_id, brand, sum(quantity*amount) as sales
from sales_data a
inner join (
select distinct customer_id
from sales_data
where lower(brand) = 'chanel'
and quantity > 0
and date >= to_date('01/01/2017','MM/DD/YYYY')
) b
on a.customer_id = b.customer_id
where date >= to_date('01/01/2017','MM/DD/YYYY')
and quantity > 0
group by customer_id, brand
Inner join in the same table sometimes required if you fill all your data in one single table with redundant information. For the table description (You explained), there could have Three different table easily - customer, brand & sales_details with appropriate relational key. And that case no Self Join (inner join in the same table) not required. But as data is available in a single table, the requirement actually lead you to the necessity of using a Self Join query. As per output of the query, its clear that you need this following requirement steps-
First you need a distinct list of customer who are selling product with brand='chanel'
Secondly, you need all product selling details for those selected customers in step one.
To avail results for above requirement, a Self Join is required.
Other Question: How can you re-write the query avoiding Inner join to pic the same result?
Ans: You can simply use a inner query in the where statement as below to get the same result-
select customer_id, brand, sum(quantity*amount) as sales
from sales_data a
where date >= to_date('01/01/2017','MM/DD/YYYY')
and quantity > 0
and a.customer_id IN (
select distinct customer_id
from sales_data
where lower(brand) = 'chanel'
and quantity > 0
and date >= to_date('01/01/2017','MM/DD/YYYY')
)
group by customer_id, brand
Your sales_data table presumably contains data for all of the sales of customers. So lets say you wanted to ask a question such as:
What is the total sales revenue for customers that have purchased 'chanel' brand?
The first thing you need to do is identify all of the customers that have purchased 'chanel' then you need to go and get all of their other sales to determine the total revenue.
The inner/sub query does exactly that it identifies the customers that have purchased 'chanel' brand since 1/1/2017.
select distinct customer_id
from sales_data
where lower(brand) = 'chanel'
and quantity > 0
and date >= to_date('01/01/2017','MM/DD/YYYY')
The outer query then joins to those customers and gets all of the sales data by brand by customer since 1/1/2017 that have a positive quantity.
select customer_id, brand, sum(quantity*amount) as sales
from sales_data a
inner join (
Customers That Purchased 'Chanel'
) b
on a.customer_id = b.customer_id
where date >= to_date('01/01/2017','MM/DD/YYYY')
and quantity > 0
group by customer_id, brand
There are methods of using EXISTS or IN to accomplish the same thing. However be very careful of IN if a customer_id could be NULL.
Yes, you are right you can do with one referencing to the table. The inner join gets particular rows and then calculated their sales value. You can do this directly:
select customer_id, brand, sum(CASE WHEN and lower(brand) = 'chanel' THEN quantity*amount ELSE 0 END) as sales
from sales_data
where date >= to_date('01/01/2017','MM/DD/YYYY')
and quantity > 0
group by customer_id, brand
having MAX(CASE WHEN lower(brand) = 'chanel' THEN 1 ELSE 0 END) = 1;
I have 2 tables with data.
The first table cus contains the customer data. The second table invoice contains the invoices created by the customer.
I want to select the total created invoices and the total sum of the invoices per customer.
Here is what I have:
SELECT cus.cus_id, cus.name_cus, count(invoice.id) as id2, CONCAT('€ ', ROUND(SUM(invoice.total),2)) as total, cus.id
FROM cus
LEFT OUTER JOIN invoice ON cus.cus_id = invoice.cus_id
WHERE cus.user_id='2'
GROUP BY cus.cus_id
To test this I have added some data to my database. The first customer has 2 invoices with a total sum of 100 (50+50).
The second customer has 3 invoices with a total sum of 30 (10+10+10).
But the SQL code dont shows me these results.
The response is for customer 1: total invoices = 1, total = 50
The response is for customer 1: total invoices = 0, total = (empty)
Does someone know what is wrong with my SQL statement?
The database type I am using is MySQL.
Here is a sample: http://sqlfiddle.com/#!9/a9f9f/1
Try grouping up your invoice count and sum as a subquery first, like:
SELECT cus.cus_id, cus.name_cus, inv.invoice_count, inv.invoice_total, cus.id
FROM cus
LEFT OUTER JOIN
(
SELECT inv.cus_id,
COUNT(inv.id) AS invoice_count,
CONCAT('€ ', ROUND(SUM(inv.total),2)) AS invoice_total
FROM invoice inv
GROUP BY inv.cus_id
) inv
ON cus.cus_id = inv.cus_id
WHERE cus.user_id='2'
If you're using SQL Server then your query should be like this --
SELECT C.cus_id
,C.name_cus
,Count(I.id) AS NumberOfInvoices
,IsNull(Sum(I.Price), 0) AS TotalPrice
FROM Customer C
LEFT JOIN Invoice I ON C.cus_id = I.cus_id
GROUP BY C.cus_id, C.name_cus
ORDER BY C.cus_id;
This is a simple sql Query as i understood your problem. I assumed CustomerID is in both tables. I think this Query will help you.
select i.CustomerID,i.CustomerName,COUNT(i.InvoiceID) as A, SUM(i.invoicetotal) as b
from Cus c,Invoice i
where i.CustomerID=c.CustomerID
group by i.CustomerID
Find names of all customers who have loans greater than all loans at Brackendale branch.
Is this ok?
Use University;
SELECT customer_name, loan_number
FROM loan NATURAL JOIN customer
HAVING MAX(amount) > ALL (SELECT sum(loan.amount)
FROM loan
WHERE branch_name = 'Brakendale');
ALL is an un-needed keyword - it does nothing as it's the default keyword for a set (the other keyword being ANY).
It is more straightforward to leave ALL out. But you probably want a group by in there and remove loan_number, otherwise each row must be in its own group.
This query seems to make more sense to me:
SELECT customer_name, MAX(amount)
FROM loan
NATURAL JOIN customer
GROUP BY customer_name
HAVING MAX(amount) > (
SELECT sum(loan.amount)
FROM loan
WHERE branch_name = 'Brakendale');
You may want MAX rather than SUM in the other direction:
SELECT customer_name, loan_number
FROM loan NATURAL JOIN customer
HAVING SUM(amount) > (SELECT max(loan.amount)
FROM loan
WHERE branch_name = 'Brakendale'
);
This would be "All customers who have total total loans greater than the biggest loan in Brakendale". Your query was more like "All customers who have total loans greater than the sum of all outstanding loans in Brakendale".
You may even want "All customers whose outstanding loans are larger than any customer in Brakendale". This would be:
SELECT customer_name, loan_number
FROM loan NATURAL JOIN customer
HAVING SUM(amount) > (SELECT max(l.CustomerLoans)
from (select customerID, sum(l.amount) as CustomerLoans
FROM loan l
WHERE branch_name = 'Brakendale'
group by customerID
) l
);