Given two tables: customers and orders
_____CUSTOMERS
customer_id
customer_name
contact_name
....
city
country
1
Alfreds Futterkiste
Maria Ander
....
Berlin
Germany
4
Around the Horn
Thomas Hardy
....
London
UK
______ORDERS
order_id
customer_id
employee_id
....
shipper_id
10254
14
5
....
2
10355
4
6
....
1
Show the amount of orders made by each customer from London. Hint: Your solution should contain two columns: customer_id and orders
I try
SELECT *
FROM orders
INNER JOIN customers ON customers.customer_id = orders.shipper_id
WHERE city ='London';
I think you can achieve this by joining the customer and order table then selecting customer_id from customer_table, and then with an aggregate count of orders
Example query:
SELECT
c.customer_id,
count(distinct o.order_id)
FROM customers as c
LEFT JOIN orders as o on o.customer_id = c.customer_id
WHERE c.city = 'London'
GROUP BY c.customer_id
You are most of the way there. You need a couple of things:
aggregation
fix the JOIN conditions
Does joining a "customer_id" to a "shipper_id" make sense? Not really -- and especially when both tables have a customer_id.
SELECT c.customer_id, COUNT(*) as num_orders
FROM customers c INNER JOIN
orders o
ON c.customer_id = o.customer_id
WHERE c.city = 'London'
GROUP BY c.customer_id;
I switched the two tables around. I just think it is more natural to go from customers to orders.
Note that this only returns customers who have at least one order. I am guessing that to become a "customer" someone has to make an order.
Related
I have one table customer, and one bill, and one sell.
Customer table
id-----name
Bill table
id-----customer_id
Sell table
id-----customer_id-----bill_id-----qtt-----price
A customer can have the records in the sell table with customer_id, and also have the bill record in the bill table with customer_id and this bill record has record in the sell table with bill_id.
This means a customer can have direct or indirect (in this case by passing the bill table) with sell table.
Now how to join tables that retrieve the total sell of a customer with ascending or deciding order?
Any idea?
I have tried many ways for example something like below, but none of them was working:
SELECT
sell.id AS sell_id,
customer.id,
bill.id AS bill_id,
customer.`name`,
sell.quantity*sell.price AS sell_price
FROM
customer_tb customer
JOIN bill ON bill.customer_id = customer.id
JOIN sell ON sell.customer_id = customer.id OR sell.bill_id = bill.id
NOTE: In case of bill table has a record in the sell table, the customer_id column is NULL and also same for the customer sell record the bill_id is NULL, this means in the sell table in the same entry only one of the (customer_id, bill_id) column has value.
You have the customer column in your sell tables, you don't need to join with bill table.
SELECT
customer.id,
customer.name,
SUM(sell.quantity * sell.price) AS total_amount
FROM customer_tb as customer
INNER JOIN sell
On sell.customer_id = customer.id
GROUP BY customer.id
You have to group your rows by the customer to get their sum independently
Your challenge is to look up the correct Customer.name for each Sell row.
You need to join Sell to Customer, and also join Sell to Bill to Customer.
How to do this?
FROM Sell s
LEFT JOIN Cust c1 ON s.customer_id = c1.id
LEFT JOIN Bill b on s.bill_id = b.id
LEFT JOIN Cust c2 ON b.customer_id = c2.id
That gives us:
s.id: the Sale id
s.quantity, s.price: the business details of the Sale
c1.name: the Customer name directly from the Sale's customer_id
c2.name: the Customer name indirectly through the Sale's bill_id
Because we use LEFT JOINs, either name can be NULL depending on which ids are null. And, I believe you favor using the direct name over the indirect name if you have both.
That means we use COALESCE() to choose one name from the two. Something like this
SELECT s.id, s.Quantity, s.Price,
COALESCE (c1.name, c2.name) name,
COALESCE (c1.id, c2.id) customer_id
FROM Sell s
LEFT JOIN Cust c1 ON s.customer_id = c1.id
LEFT JOIN Bill b on s.bill_id = b.id
LEFT JOIN Cust c2 ON b.customer_id = c2.id
But, if you have a chance to rework this database before you put a ton of data into it, please consider redesigning things to get rid of this ambiguity. It's going to drive you mad and cost you bigger servers if you have to make it work well with megarows.
I have two tables in the same database, one called "products" and the other called "customers", I need to get the customer.order_id, customer.name, customer.order_total, products.type But the thing is that I need matching result only if there is one product for this customer, so if the customer have more than one product on the other table ignore it and skip to the next one.
I have the following SQL that inner joins exactly what I need,but I don't know how to filter the results based on the product count (i don't even want to display the customer if he got more than one product.
For Example
Customers Table
order_id name order_total
13445 John 650
28837 Steve 300
20039 Craig 200
39487 Matt 475
Products Table
order_id product_sku product_price product_type
13445 12345 650 Toys
28837 34434 175 Pool
28837 54453 125 Food
20039 43546 200 Toys
39487 34256 475 Food
What i need from this two tables is:
order_id name order_total product_type
13445 John 650 Toys
20039 Craig 200 Toys
39487 Matt 475 Food
I've tried something like that, But it gets me all the result including customers with more than one product
SELECT customer.order_id, customer.name, customer.order_total, products.type
FROM customer
INNER JOIN products
ON customer.order_id=products.order_id
WHERE customer.order_total != 0
ORDER BY customer.order_id DESC
Please help, Thank you
Both should work:
select c.*,p.product_type from Customers as c, Products as p where c.order_id = p.order_id and c.order_id in
(select order_id from Products group by(order_id) having count(order_id) = 1);
select c.*, p.product_type from Products as p , Customers as c where c.order_id = p.order_id group by(p.order_id) having count(p.order_id) = 1;
I want to select the most expensive product each customer bought, but I have the information in 3 tables: Customers, Purchases, ProductsPrices.
Tables look like:
Customers:
Customer_ID | Customer_Name
Purchases:
Customer_ID | Product_ID
ProductPrices:
Product_ID | Price
What i'm running is:
SELECT
Customer_Name, max(Price), Purchases.Product_ID
FROM Customers
LEFT JOIN Purchases
ON Customers.Customer_ID=Purchases.Customer_ID
LEFT JOIN ProductPrices
ON Purchases.Product_ID=ProductPrices.Product_ID
GROUP BY Customer_Name
ORDER BY ABS(Price) DESC
;
And the output i'm getting is the names and the highest purchase correct, but the product_id is the first, and not associated with the highest price.
Can you help me to spot what am I doing wrong?
EDIT:
To make it easier for you, I created this:
http://sqlfiddle.com/#!2/db7f9/1
Try this:
select distinct c.Customer_Name,pp.Product_Id,m.Price
from
(select Customer_ID,max(Price) as Price
from Purchases p join ProductPrices pp on (p.Product_ID=pp.Product_ID)
group by Customer_ID) m
join Customers c on (m.Customer_ID=c.Customer_ID)
join ProductPrices pp on (pp.Price=m.Price)
join Purchases p on (m.Customer_ID=p.Customer_ID and p.Product_ID=pp.Product_ID)
Note: If a customer purchased multiple products with the same price, this will give you muliple rows per Customer.
try this
SELECT Customer_Name, max(Price) price , Product_ID FROM (
SELECT
Customer_Name, Price, Purchases.Product_ID
FROM Customers
INNER JOIN Purchases
ON Customers.Customer_ID=Purchases.Customer_ID
INNER JOIN ProductPrices
ON Purchases.Product_ID=ProductPrices.Product_ID
ORDER BY ABS(Price) DESC
)t
GROUP BY Customer_Name
DEMO HERE
OUTPUT:
CUSTOMER_NAME PRICE PRODUCT_ID
John 30000 3
Kate 30000 3
Peter 20000 2
I have 2 tables in mySQL database :
customers
============
customer_id (1, 2 )
customer_name (john, mark)
orders
============
order_id = 123
customer_id = 1
customer_from_id = 2
Idea is to do single query on orders table joining customers table whereby
orders.customer_id = customers.customer_id
orders.customer_from_id = customers.customer_id
to get the "customer_name" by JOIN(ing) two tables.
So how do i do single query on "orders" and expand all (2) "customer_name" fields so result looks like this :
+--------+------------+---------------------+------------------+---------------------+
order_id customer_id customer_order_name customer_from_id customer_from_name
+--------+------------+---------------------+------------------+---------------------+
123 1 john 2 mark
+--------+------------+---------------------+------------------+---------------------+
It means using same table 2x in a query and
aliasing output field "customer_name" 2x with
"customer_order_name" and "customer_from_name".
It shall be simple but i am stuck.
Any help would be much appreciated.
Thank You.
Join twice and use prefix and give aliases:
select order_id, buyer.customer_id, buyer.customer_name, seller.customer_id as customer_from_id, seller.customer_name as customer_from_name from orders o
join customers seller on o.customer_from_id = seller.customer_id
join customers buyer on o.customer_id = buyer.customer_id;
select order_id, c1.customer_id as customer_id,
c1.customer_name as customer_order_name ,
c2.customer_id as customer_from_id,
c2.customer_name as customer_from_name
from orders o
left join customers c1 using (customer_id)
left join customers c2 on o.customer_from_id = c2.customer_id;
fiddle
I've been struggling with this query.
I have two tables. One with coupons and Invoicenumbers. One with Invoicenumbers and customer names.
I need to get the customers who have not used a given coupon.
Here are the tables:
Promotion table:
Promotions
Invoice | Coupon
----------------
1 | couponA
2 | couponB
3 | couponB
Orders Table:
Orders
Invoice | Customer
------------------
1 | Jack
2 | Jack
3 | Jill
So Jack has used coupons A and B. And Jill has only used coupon B.
If my query were select customers who have not used coupon A, I should get Jill.
This works, but it seems clumsy and slow. Is there a better way?
SELECT Customer
FROM Promotions INNER JOIN Orders
ON Promotions.Invoice = Orders.Invoice
WHERE Customer NOT IN(
SELECT Customer
FROM Promotions INNER JOIN Orders
ON Promotions.Invoice = Orders.Invoice
WHERE Coupon = couponA)
GROUP BY Customer
Thanks for looking!
edit:
Here's an SQLFiddle schema
http://sqlfiddle.com/#!2/21d31/6
Updated: We should use prefer to use joins for better performance when its easy to do for us. Join vs. sub-query
Sql Fiddle
Select distinct Customer from orders o
join
(
SELECT distinct Customer as changedname FROM Orders o2
join
(
Select distinct invoice from Promotions where Coupon='couponA'
) t3
on o2.invoice = t3.invoice
) t2
on o.customer != t2.changedname;
Note: I changed column name customer for t3 because two joined tables must have different column names
Explanation:
Using inner or sub query is expensive when you have big data. use joins instead, lets learn converting subquery to join
With Subquery We had:
Select distinct Customer from orders where customer not in
(SELECT distinct Customer FROM Orders where invoice in
(Select distinct invoice from Promotions where Coupon='couponA'));
Converting sub-query to join
First step:
Select distinct Customer from orders o
join
(
SELECT distinct Customer as changedname FROM Orders where invoice in
(Select distinct invoice from Promotions where Coupon='couponA')
) t2
on o.customer != t2.changedname;
2nd step:
Select distinct Customer from orders o
join
(
SELECT distinct Customer as changedname FROM Orders o2 where invoice
join
(
Select distinct invoice from Promotions where Coupon='couponA'
) t3
on o2.invoice = t3.invoice
) t2
on o.customer != t2.changedname;
And that's it, much faster for tables having numerous rows
Original answer:
Use not in. Have a look.
Select distinct Customer from orders where customer not in
(SELECT distinct Customer FROM Orders where invoice in
(Select distinct invoice from Promotions where Coupon='couponA'));
Edit I have added distinct to make query faster
SQL Fiddle
SELECT DISTINCT o2.customer FROM ORDER o2
LEFT JOIN (promotions p1
JOIN Orders o1 ON p1.cuopon = 'CuoponA' AND p1.invoice = o1.invoice ) p3
ON o2.customer = p3.customer
WHERE p3.customer IS NULL
Try this query instead:
SELECT DISTINCT Customer
FROM Orders o1
WHERE NOT EXISTS (
SELECT 1
FROM Orders o2
INNER JOIN Promotions ON Promotions.Invoice = o2.Invoice
WHERE o1.Customer = o2.Customer AND Coupon = 'couponB')
The idea is to get rid of the GROUP BY by removing a join in the top part of the query, and also eliminate the NOT IN by making a coordinated subquery.
Here is a link to sqlfiddle.
Try this with a right join
SELECT Customer, Coupon
FROM Promotions
RIGHT JOIN Orders ON Promotions.Invoice = Orders.Invoice
AND Coupon = 'couponA'
GROUP BY Customer
HAVING Coupon IS NULL