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
);
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.
I am using MySQL and I have 3 tables which are customers, debits, and credits. Each customer has one or multiple debits and one or multiple credits. Now I want to calculate the total debit and total credit of each customer and just show those customers who are not balanced in total debit and total credit. Can anyone help me?
One idea would be to left join two aggregate queries that compute the total credit and debit for each customer, and filter in the outer query.
Something like:
select cus.*
from customers cus
left join (select customer_id, sum(amount) total_amount from credits group by customer_id) cre
on cre.customer_id = cus.customer_id
left join (select customer_id, sum(amount) total_amount from debits group by customer_id) deb
on deb.customer_id = cus.customer_id
where coalesce(cre.total_amount, 0) = coalesce(deb.customer_id, 0)
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 want to write a SQL query to compute which customers have purchased more than 4 products on the same day.
Here are my tables:
Sales
(date, customer_id, product_id, units_sold)
Products
(id, name, price)
Customers
(id, name)
& here's what I have so far:
SELECT COUNT(s.product_id) as total_customers
FROM Sales s1
WHERE DATEDIFF(s1.date, s2.date)=0
INNER JOIN Sales s2
ON s1.product_id = s2.product_id
HAVING COUNT(s.product_id) > 4;
If you want the customers who have purchased more than 4 products on the same date:
SELECT DISTINCT s.customer_id
FROM Sales s
GROUP BY s.customer_id, date(s.date)
HAVING COUNT(*) > 4;
This is one of the few cases where SELECT DISTINCT is used with GROUP BY. If you want to know the dates as well, then include date(s.date) in the SELECT.
Note that this assumes that any given product is purchased by a customer only once on each date. If a customer can have multiple records for a single product on one date, use COUNT(DISTINCT product_id) instead of COUNT(*).
To get the total number of customers, use a subquery:
SELECT COUNT(*)
FROM (SELECT DISTINCT s.customer_id
FROM Sales s
GROUP BY s.customer_id, date(s.date)
HAVING COUNT(*) > 4
) c
Too many mistakes's in your query try this
SELECT customer_id,cast(s1.date as date),COUNT(s1.product_id) as total_customers
FROM Sales s1
Group by customer_id,cast(s1.date as date)
HAVING COUNT(s1.product_id) > 4;
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