How can I show order quantity relative to cities where customers in cities have at least three orders? - sql

I use this SQL statement to be able to join three tables (Order1, Order2, and Customers) to show the order quantity for each customer from each city they're addressed to. But how can I show the rows of order quantities for customers in cities who have done at least three orders? In other words I'm trying to aggregate on the cities connected to the customers who have done more than three orders.
Table structures:
Customers has the columns CustomerNr, City Name
Order1 has the columns Ordernr, CustomerNr
Order2 has the columns Ordernr, Order quantity
The SQL statement so far:
SELECT
Customers.CityName, Order2.OrderQuantity
FROM
Order1
INNER JOIN
Order2 ON Order1.ordernr = Order2.ordernr
INNER JOIN
Customers ON Customers.CustomerNr = Order1.CustomerNr

What you're missing are aggregate functions. To get the sum of a column, you can use SUM(columnName) in your select statement. To get proper results, you will have to group by a field as well. In this case, you want the sum per customer so you can do something like this:
SELECT c.customerNumber, c.name, SUM(o2.quantity) AS totalQuantity
FROM customers c
JOIN order1 o1 ON o1.customerNumber = c.customerNumber
JOIN order2 o2 ON o2.orderNumber = o1.orderNumber
GROUP BY c.customerNumber, c.name;
To filter on an aggregate condition, you need to add a having clause. Here, you can require that each group have a minimum of 3 rows:
SELECT c.customerNumber, c.name, SUM(o2.quantity) AS totalQuantity
FROM customers c
JOIN order1 o1 ON o1.customerNumber = c.customerNumber
JOIN order2 o2 ON o2.orderNumber = o1.orderNumber
GROUP BY c.customerNumber, c.name
HAVING COUNT(*) >= 3;
Here is an SQL Fiddle with some dummy data that I tested with.

select c.CityName, Sum(o2.OrderQuantity) as Quantity
from Customers c
inner join Order1 o1 on c.CustomerNr = o1.CustomerNr
inner join Order2 o2 on o1.OrderNr = o2.OrderNr
group by c.CityName
having sum(o2.OrderQuantity) >= 3

Related

Display 2 columns from one table having max count in column 3 and display computed sum of values from another table

I've a customer table and purchases table,
need to show cname, cid with max(customer_visits) from customer table
and sum of total_purchases by customer in purchases table.
I'm doing something like this
select p.cid, c.cname, sum(p.total_price)
from customers c where exists
(select max(visits_made) from customers having visits_made=max(visits_made)
and cid=p.cid)
inner join purchases p on p.cid=c.cid
group by p.cid,c.cname
and
select p.cid, c.cname, sum(p.total_price)
(select max(visits_made) from customers c where c.cid=p.cid)
from purchases p
inner join customers c on c.cid=p.cid
group by p.cid,c.cname
What's going wrong with these queries?
Found the solution, had to include where clause after inner join :D
I think this is just an aggregation query:
select p.cid, c.cname, sum(p.total_price) as total_price,
max(visits_made) as visits_made
from purchases p inner join
customers c
on c.cid = p.cid
group by p.cid, c.cname;

How do a join three tables where one table doesn't match the ID of the other two?

I'm trying to figure out how to solve this question with a proper SQL statement:
"How much has been sold to all customers in cities where a customer has made at least three orders. The result should display the city name and the total order quantity for these customers".
The thing is that I have three tables to work with: Order1, Order2, and Customers. The table structures for these look like this:
Order1 has the attributes: Ordernr, CustomerNr.
Order2 has the attributes: Ordernr, Order quantity.
Customers has the attributes: CustomerNr, Customer name, City name.
With this code I can join the three tables to be able to show the order quantity for each customer from each city. But how can I show the order quantity for customers in cities who've at least three orders?
SELECT Customers.CustomerNr, CityName, Order2.OrderQuantity
FROM Order1 INNER JOIN Order2
ON Order1.ordernr = Order2.ordernr JOIN Customers
ON Customers.CustomerNr = Order1.CustomerNr
Try this:
SELECT c.CityName, SUM(o2.OrderQuantity) OrderQuantity
FROM Order1 o1
INNER JOIN (SELECT o1.CustomerNr
FROM Order1 o1
GROUP BY o1.CustomerNr
HAVING COUNT(o1.Ordernr) >= 3
) AS a ON o1.CustomerNr = a.CustomerNr
INNER JOIN Order2 o2 ON o1.Ordernr = o2.Ordernr
INNER JOIN Customers c ON o1.CustomerNr = c.CustomerNr
GROUP BY c.CityName
This query will return a list of cities with at least 3 orders:
select CityName
from Customers c
join Order1 o1 on c.CustomerNr = o1.CustomerNr
join Order2 o2 on o1.OrderNr = o2.OrderNr
group by c.CityName having Sum(o2.OrderQuantity) > 3
Now you want all orders (I suppose from table Order1) from customers from these cities
select o1.*
from Order1 o1 joib Customer c on c.CustomerNr = o.CustomerNr
where c.CityName in (
select CityName
from Customers c
join Order1 o1 on c.CustomerNr = o1.CustomerNr
join Order2 o2 on o1.OrderNr = o2.OrderNr
group by c.CityName having Sum(o2.OrderQuantity) > 3
)
Hope this helps

Oracle: Using Sub-Queries, JOIN and distinct function together

Here is how I contructed the step-by-step:
M1. create a sub-query that will return CustomerId and total invoiced for that customer
M2. A second subquery that will give a list of distinct ProductIDs (along with product SKUs) and CustomerIDs.
M3. The M1 and M2 subqueries will be joined to make association between customer totals and products (for the same CustomerId).
M4. The query M3 will be fed to the final query that will just find the top 5 products.
I'm stuck on creating the distinct ProductID and customerID because they would have to be in aggregate functions in order to make them distinct.
Attached is an image that is the erwin diagram which helps understand the system.
If you can help me with M1-M4, I will greatly appreciate it. I'm not a programmer by trade but a business analyst.
--M1--
select C.CustomerId, COUNT(I.InvoiceId) TotalNumInvoices
from Customer C
JOIN Invoice I ON (I.CustomerId = C.CustomerId)
group by C.CustomerId
--M2: Incomplete--
select P.ProductID, P.SKU, C.CustomerID
from Product P
JOIN InvoiceLine IL ON (IL.ProductId = P.ProductId)
JOIN Invoice I ON (IL.InvoiceId = I.InvoiceId)
JOIN Customer C ON (C.CustomerId = I.CustomerId)
you can also use the DISTINCT keyword your select clause in order to get unique values. Try this for m2:
select DISTINCT p.productID, p.sku, i.customerID
from invoice i INNER JOIN invoiceLine il
ON i.invoiceID = il.invoiceID
JOIN product p
ON il.productID = p.productID;

SQL Server: fill Null Fields from Not Null Column for multiple rows having same id

I built following Select query to get below results
SELECT Orders.OrderID, OrderDetails.ProductCode, OrderDetails.Coupon
From Orders, OrderDetails
WHERE Orders.OrderID=OrderDetails.OrderID
Results
Order ID Product Code Coupon
22 A
22 B XYZ
22 C
23 D 123
24 E
I want it to display like this:
Order ID Product Code Coupon
22 A XYZ
22 B XYZ
22 C XYZ
23 D 123
24 E
so that it fills empty coupons from not empty coupon field where order id matches.
Your help will be greatly appreciated. Thanks.
SELECT
t1.OrderID,
t1.ProductCode,
MAX(ISNULL(t2.Coupon,'')) as CouponCode,
t1.CustomerName
--Here you have select list by using alias 't'
--don't forget it to add in group by clause
FROM
(
select O.OrderID,OD.ProductCode,OD.CouponCode as Coupon,C.CustomerName
--Here add the list of columns
from Orders O
inner join OrderDetails OD on O.OrderID=OD.OrderID
Inner join customers C on O.CustomerID=C.CustomerID
)t1
INNER JOIN (
select O.OrderID
from Orders O
inner join OrderDetails OD on O.OrderID=OD.OrderID
Inner join customers C on O.CustomerID=C.CustomerID
)t2 ON
CAST(t1.OrderID AS VARCHAR)=
CAST(t2.OrderID AS VARCHAR)
GROUP BY t1.OrderID,
t1.ProductCode,
t1.CustomerName
--Add the extra fields.
order by t1.OrderID
SQL Fiddle with Your Data
Assuming Coupon is unique for each OrderID.
SELECT o1.OrderID, o2.Coupon
FROM OrderDetails o1 LEFT JOIN
(SELECT DISTINCT OrderID, Coupon FROM OrderDetails WHERE NOT Coupon IS NULL) AS o2 ON o1.OrderID = o2.OrderID
This is kind of ugly but does the job:
SELECT o.OrderID, od1.ProductCode, COALESCE(od1.Coupon,od2.Coupon)
From
Orders o
inner join
OrderDetails od1
on
o.OrderID=od1.OrderID
left join
(select OrderID,MAX(Coupon) as Coupon from OrderDetails
where Coupon is not null group by OrderID) od2
on
o.OrderID=od2.OrderID
It's using GROUP BY and MAX to ensure that there's only one row in od2 for each OrderID value, even if multiple rows in OrderDetails already have Coupon set.

Fetch data from more than one tables using Group By

I am using three tables in a PostgreSql database as:
Customer(Id, Name, City),
Product(Id, Name, Price),
Orders(Customer_Id, Product_Id, Date)
and I want to execute a query to get from them "the customers that have have ordered at least two different products alnong with the products". The query I write is:
select c.*, p.*
from customer c
join orders o on o.customer_id = c.id
join product p on p.id = o.product_id
group by (c.id)
having count(distinct o.product_id)>=2
It throws the error:
"column "p.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: select c.*, p.*".
However if I remove the the p.* from select statement (assuming that I one does not want the products, only the customers), it runs fine. How can I get the products as well?
Update: Having ordered two or more products, a customer must appear on the output as many times as its product he has ordered. I want as output a table with 5 columns:
Cust ID | Cust Name | Cust City | Prod ID | Prod Name | Prod Price
Is it possible in SQL given that group by should be used? Shoul it be used on more than one columns on different tables?
Try this out :
SELECT distinct c.* ,p.*
FROM Customer c
JOIN
(SELECT o.customer_id cid
FROM Product P
JOIN Orders o
ON p.id= o.product_id
GROUP BY o.customer_id
HAVING COUNT(distinct o.product_id)>=2) cp
ON c.id =cp.cid
JOIN Orders o
on c.id=o.customer_id
JOIN Product p
ON o.product_id =p.id
I hope it solves your problem.
I think you can use following query for this question -
SELECT C1.*, p1.*
FROM Customer C1
JOIN Orders O1 ON O1.Customer_Id = C1.Id
JOIN Product P1 ON P1.Id = O1.Product_Id
WHERE C1.Id IN (SELECT c.Id
FROM Customer c
JOIN Orders o ON o.Customer_Id = c.Id
GROUP BY (c.Id)
HAVING COUNT(DISTINCT o.Product_Id) >= 2)