MySQL - Using subqueries on join and from - mysql

I am trying to return the CustomerID, CompanyName, OrderID, and subtotals for each customer for all order the subtotal amounts that are higher than the customer’s average subtotal amount. These are the tables I am using and the query below. I am unsure if the values I return are correct and was hoping someone could help me understand if they are or not based on my query. Thanks in advance.
Orders
Columns
OrderID
CustomerID
EmployeeID
OrderDate
RequiredDate
OrderDetails
Columns
OrderID
ProductID
UnitPrice
Quantity
Products
Columns
ProductID
ProductName
QuantityPerUnit
UnitPrice
Customers
Columns
CustomerID
CompanyName
ContactName
Country
SELECT A.CustomerID, A.CompanyName, A.Subtotal, A.OrderID, AVGSubtotal
FROM (
SELECT
C.CustomerID,
C.CompanyName,
(D.UnitPrice * P.QuantityPerUnit) AS Subtotal,
D.OrderID
FROM Customers C
JOIN Orders O ON C.CustomerID = O.CustomerID
JOIN OrderDetails D ON D.OrderID = O.OrderID
JOIN Products P ON P.ProductID = D.ProductID
GROUP BY
D.OrderID, C.CustomerID
) A
JOIN (
SELECT
S.CustomerID, S.CompanyName, AVG(S.Subtotal) as AVGSubtotal
FROM (
SELECT
C.CustomerID,
C.CompanyName,
(D.UnitPrice * P.QuantityPerUnit) AS Subtotal
FROM Customers C
JOIN Orders O ON C.CustomerID = O.CustomerID
JOIN OrderDetails D ON D.OrderID = O.OrderID
JOIN Products P ON P.ProductID = D.ProductID
GROUP BY
D.OrderID, C.CustomerID
) S
GROUP BY
S.CustomerID
) B ON A.CustomerID = B.CustomerID
WHERE
A.CustomerID = B.CustomerID AND
A.Subtotal > B.AVGSubtotal
ORDER BY
A.CustomerID, A.CompanyName
;

select
c2.customerID,
c2.CompanyName,
c2.AVGSubtotal
o2.OrderID,
o2.UnitPrice * o2.Quantity as subtotal
from (
select
c.CustomerID,
c.CompanyName,
sum(o.UnitPrice * o.Quantity)/count(*) as AVGSubtotal
from
Customers c
inner join Orders o on (o.CustomerID = c.CustomerID)
inner join OrderDetails od on (od.OrderID = c.OrderID)
group by
o.CustomerID
) as c2
inner join Orders o2 on (o2.CustomerID = c2.CustomerID)
where o2.UnitPrice * o2.Quantity > c2.AVGSubtotal

Related

Most efficient way to to find most expensive recent order

I am trying to find most recent and expensive purchase by customer. I have four tables customers,orders,order details and product code. All accounts are unique by emailaddress.
Error The multi-part identifier "cx.EmailAddress" could not be bound
SELECT c.EmailAddress,
o.BillingFirstName AS WC_FirstName,
o2.LatestOrder
FROM Customers c
JOIN orders o ON o.customerid = c.customerid
JOIN( SELECT
cx.EmailAddress,
MAX(o.OrderID) AS LatestOrder
FROM Customers AS cx
JOIN Orders o ON o.customerid = cx.customerid
WHERE o.OrderStatus <> 'CANCELLED' AND o.OrderDate > '09/01/2017 00:00'
GROUP BY EmailAddress) AS o2 on o2.EmailAddress = cx.EmailAddress
GROUP BY c.EmailAddress,o.BillingFirstName
UPDATE Tried it in another way too but still gets error : The multi-part identifier "c.EmailAddress" could not be bound.
SELECT
c.EmailAddress,
c.CustomerID,
o.OrderDate,
p.Google_Gender,
p.Google_Age_Group ,
p.productprice AS Product_Price
FROM
Customers c
JOIN
orders o ON o.CustomerID = c.CustomerID
JOIN
(SELECT
c.EmailAddress,
MAX(o.OrderID) AS LatestOrder
FROM
Orders o, Customers c
WHERE
o.OrderStatus <> 'CANCELLED' AND
o.CustomerID = c.CustomerID
GROUP BY
c.EmailAddress) AS o2 ON o2.EmailAddress = c.EmailAddress
JOIN
(SELECT
od.*,
c.EmailAddress,
row_number() over (partition BY c.EmailAddress
ORDER BY od.ProductPrice DESC, o.OrderDate DESC) AS seqnum
FROM
OrderDetails od
JOIN
Orders o ON od.OrderID = o.OrderID
JOIN
Customers c ON o.CustomerID = c.CustomerID
JOIN
(SELECT
c.EmailAddress,
MAX(o.OrderID) AS LatestOrder
FROM
Orders o , Customers c
WHERE
o.OrderStatus <> 'CANCELLED' AND
o.CustomerID = c.CustomerID
GROUP BY
c.EmailAddress) AS o2 ON o2.EmailAddress = c.EmailAddress
WHERE
o.OrderID = o2.LatestOrder) od ON od.CustomerID = c.CustomerID
AND seqnum = 1
JOIN
Products_Joined p ON od.ProductCode = p.ProductCode
FULL JOIN
(SELECT p.ProductCode, p.ProductName FROM Products_Joined AS p) AS p2 ON p2.ProductCode = p.Google_Age_Group
WHERE
AND o.PaymentAmount <> 0
AND o.OrderID = o2.LatestOrder
GROUP BY
c.EmailAddress, o.OrderDate, c.CustomerID, p.productprice,
p.Google_Age_Group, p.Google_Gender, p.Google_Pattern,
p.Google_Size, od.ProductName, p.ProductName, p2.productname,
p.productcode
ORDER BY
o.OrderDate DESC, MAX(od.ProductPrice) DESC;
You have that error because cx is an internal alias inside the o2 query. So you should probably change that JOIN condition for this one:
AS o2 on o2.EmailAddress = c.EmailAddress
This way you join your o2 email address with the one from Customers directly.
Just for the sake of performance, it would be better if you join customers by CustomerID, like you do in your first join, instead of by email.
Finally, you are doing the MAX of OrderID, which will most likely return the most recent order. Having that in mind, you should probably change your query to something like this (I'm guessing Amount is the name of the field):
SELECT c.EmailAddress,
o.BillingFirstName AS WC_FirstName,
MostExpensiveOrderId = o.OrderId,
MostExpensiveOrderAmount = o.Amount
FROM Customers c
INNER JOIN (
SELECT
CustomerID,
MAX(Amount)
FROM Orders
WHERE OrderStatus <> 'CANCELLED' AND OrderDate > '09/01/2017 00:00'
GROUP BY CustomerID
) AS omax ON omax.CustomerID = C.CustomerID
INNER JOIN Orders o ON o.CustomerID = c.CustomerID AND o.Amount = omax.Amount
ORDER BY c.EmailAddress, o.BillingFirstName
Note that you don't need the Customers table in the inner query. Also note that this way you may get more than one row per customer if the highest value is shared with more than one order.

MySQL - Using subquery to find an average

I am having trouble with the syntax of this query. I am trying to return the largest total for one company from each country.
The tables look like:
Orders
Columns
OrderID
CustomerID
EmployeeID
OrderDate
RequiredDate
OrderDetails
Columns
OrderID
ProductID
UnitPrice
Quantity
Products
Columns
ProductID
ProductName
QuantityPerUnit
UnitPrice
Customers
Columns
CustomerID
CompanyName
ContactName
Country
I have tried the following:
SELECT
T1.Country,
CompanyName,
T1.OrderSum
FROM
(SELECT
C.Country,
C.CompanyName,
SUM(UnitPrice * Quantity) AS OrderSum
FROM Customers C
JOIN Orders O
ON C.CustomerID = O.CustomerID
JOIN OrderDetails D
ON D.OrderID = O.OrderID
GROUP BY C.Country) T1
JOIN
-- TOP PAYMENT TOTALS BY COUNTRY
(SELECT COUNTRY,
MAX(OrderSum) AS OrderSum
FROM
-- PAYMENT TOTALS BY CUSTOMER
(SELECT C.Country,
C.CompanyName,
SUM(UnitPrice * Quantity) AS OrderSum
FROM Customers C
JOIN Orders O1
ON O1.CustomerID = C.CustomerID
JOIN OrderDetails D1
ON D1.OrderID = O1.OrderID
GROUP BY C.COUNTRY, C.CompanyName) T2
GROUP BY COUNTRY) T3
ON T1.COUNTRY = T3.COUNTRY
AND T1.OrderSum = T3.OrderSum
ORDER BY Country;
This query only returns three countries:
Ireland Hungry Owl All-Night Grocers 57317.3900
Norway Sant Gourmet 5735.1500
Poland Wolski Zajazd 3531.9500
But, this query I tried, returns all countries, but I am not sure if it is correct because I did not include the 'max' value as I did in the previous query:
SELECT
T1.Country,
CompanyName,
T1.OrderSum
FROM
(SELECT
C.Country,
C.CompanyName,
SUM(UnitPrice * Quantity) AS OrderSum
FROM Customers C
JOIN Orders O
ON C.CustomerID = O.CustomerID
JOIN OrderDetails D
ON D.OrderID = O.OrderID
GROUP BY C.CompanyName) T1
GROUP By Country
ORDER BY Country;
I am also unsure if I am calculating the order totals correctly, which may be the mistake on my part. But I am trying to find the company from each country that has the largest order total.
Sorry for all the text.
The following query would list only the companies with the largest order total per country:
SELECT A.Country, A.CompanyName, A.OrderSum
FROM (
SELECT
C.Country,
C.CompanyName,
SUM(D.UnitPrice * D.Quantity) AS OrderSum
FROM Customers C
JOIN Orders O ON C.CustomerID = O.CustomerID
JOIN OrderDetails D ON D.OrderID = O.OrderID
GROUP BY
C.Country, C.CustomerID
) A
JOIN (
SELECT
S.Country, MAX(S.OrderSum) as MaxSum
FROM (
SELECT
C.Country,
C.CompanyName,
SUM(D.UnitPrice * D.Quantity) AS OrderSum
FROM Customers C
JOIN Orders O ON C.CustomerID = O.CustomerID
JOIN OrderDetails D ON D.OrderID = O.OrderID
GROUP BY
C.Country, C.CustomerID
) S
GROUP BY
S.Country
) B ON A.Country = B.Country
WHERE
A.Country = B.Country AND
A.OrderSum = B.MaxSum
ORDER BY
A.Country, A.CompanyName
;
[UPDATE]
Note that the above SQL follows the way OrderSum is calculated in your listed queries. Given that table Products has QuantityPerUnit and UnitPrice, I suspect that your OrderSum should be multiplied by QuantityPerUnit as well – in which case you'll need to revise the math for OrderSum.

MYSQL Queries - combination

I need to find the first and last name of the customer who has purchased the most expensive product.
Schema
Orders
orderID
ordertypeID
customerID
quantity
purchasedate
Customers
customerID
state
postcode
streetNumber
streetAddress
customerLn
customerFn
Order_Contents
orderID
productID
quantity
Products
productID
productCategory
productName
productDescription
unitPrice
inStock
How can i write this query?
You can use sub queries as follows.
select
Customers.customerFN,
Customers.customerLN
from
Customers
inner join Orders on Orders.customerID = Customers.customerID
inner join Order_Contents on Order_Contents.orderID = Orders.orderID
where
Order_Contents.productID in
(select Products.productID from Products where Products.unitPrice = (select max(Products.unitPrice) from Products))
Something like this seems like it should work as a jumping off point (completely naive approach here)
SELECT CustomerFn, CustomerLn FROM Customers c
LEFT JOIN Orders o on o.customerID = c.customerID
LEFT JOIN Order_Contents oc on oc.orderID = o.orderID
LEFT JOIN Products p on p.productID = oc.productID
WHERE oc.productID IN (
SELECT productID FROM Products WHERE unitPrice = MAX(unitPrice)
);
select c.customerFn, c.customerLn
from customers c join orders o where o.customerID = c.customerID
join order_contents l where l.orderId = o.orderId
join products p where p.productId = l.productId
order by p.unitPrice desc
limit 1

How can I combine information from 4 different tables in a SQL query?

I have a to write an SQL query to list the names and total spend of customers who made more
than one order. The following lists all the relevant information but I'm struggling to see how to move forward with this.
SELECT l.quantity, o.orderID, i.itemID, o.custID, i.unitcost, c.familyname
FROM lineitems l, orders o, items i, customers c
WHERE l.itemID = i.itemID
AND c.custID = o.custID
AND o.orderID = l.orderID
ORDER BY o.custID
Select customerId, Sum(i.quantity*i.unitCost)
From lineitems I
join orders o on o.orderID = i.orderID
where Exists(Select * From orders
where customerId = o.customerId
having count(*) > 1)
group by customerId
or, with name instead of just customerId
Select c.familyname, Sum(i.quantity*i.unitCost)
From lineitems I
join orders o on o.orderID = i.orderID
join customers c on c.customerId = o.customerId
where Exists(Select * From orders
where customerId = o.customerId
having count(*) > 1)
group by c.familyname

Complex sql query with multiple tables

I have 3 tables:
Customers
ID_CUSTOMER
NAME
Products
ID_PRODUCT
PRODUCTNAME
PRICE
Orders
ID_ORDER
CUSTOMER_ID
PRODUCT_ID
QUANTITY
How to select all customers who ordered for $10k or more?
try something like:
SELECT C.ID_CUSTOMER, C.Name,
SUM(P.PRICE * O.QUANTITY) AS Total FROM Customers C
JOIN Orders O ON C.CUSTOMER_ID = O.CUSTOMER_ID
JOIN Procucts P ON P.PRODUCT_ID = O.PRODUCT_ID
GROUP BY C.ID_CUSTOMER, C.Name
HAVING SUM(P.PRICE * O.QUANTITY) >= 10000
select c.*
from customers c
inner join orders o on o.customer_id = c.id_customer
inner join products p on p.id_product = o.product_id
group by c.id_customer
having sum(p.price * o.quantity) >= 10000
try this:
SELECT a.ID_CUSTOMER,
a.NAME
FROM CUSTOMERS a
INNER JOIN ORDERS b
ON b.CUSTOMER_ID = a.ID_CUSTOMER
INNER JOIN PRODUCTS c
ON c.ID_PRODUCT = b.product_id
GROUP BY a.ID_CUSTOMER, a.NAME
HAVING SUM(c.PRICE * b.QUANTITY) >= 10000
It is not really a complex query. Another syntax to do the same thing:
SELECT C.ID_CUSTOMER, C.NAME, SUM(P.PRICE * O.QUANTITY) TOTAL
FROM Products P, Customers C, Orders O
WHERE O.CUSTOMER_ID = C.ID_CUSTOMER
AND O.PRODUCT_ID = P.ID_PRODUCT
GROUP BY C.ID_CUSTOMER, C.NAME
HAVING SUM(P.PRICE * O.QUANTITY) >= 10000