Query not bringing associated values with max function (Northwinds Database) - mysql

I'm trying to get the product that has the highest gross value per category. I get the correct 'Grossed' amount by category, but it doesn't seem to bring the correct 'ProductID' and 'ProductName' with it.
SELECT
c.CategoryName,
prodGross.ProductID,
prodGross.ProductName,
MAX(ROUND(Grossed, 2)) AS Grossed
FROM
categories AS c
JOIN
(SELECT
p.ProductID,
p.ProductName,
p.CategoryID,
SUM(((od.UnitPrice * od.Quantity) - ((od.UnitPrice * od.Quantity) * od.Discount))) AS Grossed
FROM
northwind.`order details` AS od
JOIN products AS p ON p.ProductID = od.ProductID
GROUP BY p.ProductID) AS prodGross ON prodGross.CategoryID = c.CategoryID
GROUP BY c.CategoryName;
Any feedback would be helpful.
Thank you!

Consider derived tables of both aggregate queries matching the CategoryID and Grossed fields:
SELECT p.*, c.CategoryName, ROUND(g.MaxGrossed) AS HighestGrossed
FROM category c
INNER JOIN
(SELECT subp.ProductID, subp.ProductName, subp.CategoryID,
SUM(((od.UnitPrice * od.Quantity) -
((od.UnitPrice * od.Quantity) * od.Discount))) AS Grossed
FROM northwind.`order details` AS od
INNER JOIN products AS subp ON subp.ProductID = od.ProductID
GROUP BY subp.ProductID) As p
ON c.CategoryID = p.CategoryID
INNER JOIN
(SELECT subg.CategoryID, MAX(subg.Grossed) AS MaxGrossed
FROM
(SELECT subp.ProductID, subp.ProductName, subp.CategoryID,
SUM(((od.UnitPrice * od.Quantity) -
((od.UnitPrice * od.Quantity) * od.Discount))) AS Grossed
FROM northwind.`order details` AS od
INNER JOIN products AS subp ON subp.ProductID = od.ProductID
GROUP BY subp.ProductID) AS subg
GROUP BY subg.CategoryID) AS g
ON p.CategoryID = g.CategoryID AND p.Grossed = g.MaxGrossed
You can even save the repeated aggregate that calculates Grossed as a separate stored view and reference it in this query:
SELECT p.*, c.CategoryName, ROUND(g.MaxGrossed) AS HighestGrossed
FROM category c
INNER JOIN ProdGrossedView As p
ON c.CategoryID = p.CategoryID
INNER JOIN
(SELECT v.CategoryID, MAX(v.Grossed) AS MaxGrossed
FROM ProdGrossedView v
GROUP BY v.CategoryID) AS g
ON p.CategoryID = g.CategoryID AND p.Grossed = g.MaxGrossed

Related

Beginner sql student in need of assistance

I'm very new to sql, and Stack Overflow. I'm hoping someone can help assist me in this query. My query is supposed to display the total sales and total items sold for categories with more than $200,000 in sales. I've been working on this query for an hour and am at my wits end, and help is appreciated!
select distinct c.categoryname,
sum(p.unitprice * od.Quantity) as 'Sales'
from Categories c
inner join Products p
on c.CategoryID = p.CategoryID
inner join OrderDetails od
on p.ProductID = od.ProductID
where p.unitprice < 200000
group by c.categoryname
I'm hoping I'm at least on the right track, thanks for the help!
Try this version:
SELECT
c.categoryname,
sum(od.Quantity) as "Items Sold", -- you were missing this
sum(p.unitprice * od.Quantity) as "Sales"
FROM
Categories c
INNER JOIN Product p ON c.CategoryID = p.CategoryID,
INNER JOIN OrderDetails od on p.ProductID = od.ProductID
WHERE
sum(p.unitprice * od.Quantity) > 200000 -- filter on the sales, not product
GROUP BY
c.categoryname

How do i sub query two joins?

I have created two queries that both return the required results independent of each other. I am trying to join them to have the returned values be customerName, Amount Ordered, and Amount Paid.
Currently, this query works but only returns the customerName. How can it get the query to return the other two columns?
SELECT c1.customerName
FROM
(SELECT cc.customerName, ROUND(SUM(od.priceEach * od.quantityOrdered), 2) as '$ Amount Ordered'
FROM customers cc
INNER JOIN orders o ON o.customerNumber = cc.customerNumber
INNER JOIN orderdetails od ON od.orderNumber = o.orderNumber
GROUP BY cc.customerName
) c1
INNER JOIN
(SELECT c.customerName, ROUND(SUM(p.amount), 2) as 'Total $ Amount Paid'
FROM customers c
INNER JOIN payments p ON p.customerNumber = c.customerNumber
GROUP BY c.customerName
) c2
WHERE c1.customerName = c2.customerName
GROUP BY c1.customerName
ORDER BY c1.customerName;
this should select the others column
SELECT c1.customerName, c1.Amount_Ordered as '$ Amount Ordered', c2.Total_Amount_Paid as 'Total $ Amount Paid'
FROM
(SELECT cc.customerName, ROUND(SUM(od.priceEach * od.quantityOrdered), 2) as Amount_Ordered
FROM customers cc
INNER JOIN orders o ON o.customerNumber = cc.customerNumber
INNER JOIN orderdetails od ON od.orderNumber = o.orderNumber
GROUP BY cc.customerName
) c1
INNER JOIN
(SELECT c.customerName, ROUND(SUM(p.amount), 2) as Total_Amount_Paid
FROM customers c
INNER JOIN payments p ON p.customerNumber = c.customerNumber
GROUP BY c.customerName
) c2
WHERE c1.customerName = c2.customerName
GROUP BY c1.customerName
ORDER BY c1.customerName;
simply add them to the select section:
SELECT c1.customerName, C1.amountOrdered, C2.amountPaid FROM ...
And one more word of advice - DONT use whitespace or special signs like $ in your column names, it is bad practice. I think it's a mistake that mySql even allows it

Multiple inner joins to get a complex report, not working

For the schema below, I need to get this report
This is what I have
select c.name, sr.name, count(o.order_id)
from contact c
INNER JOIN accounts a
ON c.account_id=a.account_id
INNER JOIN sales_reps sr
ON a.sales_rep_id =sr.sales_rep_id
INNER JOIN orders o
ON a.account_id =o.account_id
where o.order_id in (
select SUM(oi.quantity*p.price) from
order_items oi INNER JOIN parts p
on oi.part_id =p.part_id
)
group by a.account_id, c.name
But this does not give any results.
Please help.
Your where condition is not right, how should be a order_id equal a sum?
Try the below:
select
c.name, sr.name, COUNT(o.order_id), SUM(op.order_total)
FROM
contact c
INNER JOIN
accounts a ON c.account_id = a.account_id
INNER JOIN
sales_reps sr ON a.sales_rep_id = sr.sales_rep_id
INNER JOIN
orders o ON a.account_id = o.account_id
INNER JOIN
(SELECT
oi.order_id, SUM(oi.quantity * p.price) AS order_total
FROM
order_items oi
INNER JOIN
parts p ON oi.part_id = p.part_id
GROUP BY
oi.order_id
) op ON o.order_id = op.order_id
WHERE o.delivery_data >= CURDATE()
GROUP by c.contact_id
It won't give results as your WHERE ... IN SELECT is based on a query returning a sum() value which will not equal a key (most likely), or incorrect at best... and since you are dealing with a quantity and price which will have decimal precision (typically), you won't even get that to match even LESS likely...
I would swap the query around to pre-qualify the orders within a given date in question and sum that... THEN join to rest...
select
c.name,
sr.name,
PreQualified.NumberOrders,
PreQualified.OrderTotal
from
( select
o.Account_ID,
count( distinct o.order_id ) as NumberOrders,
sum( oi.quantity * p.price ) as OrderTotal
from
orders o
join order_items oi
on o.order_id = oi.order_id
join parts p
on oi.part_id = p.part_id
where
o.Delivery_Date >= CURDATE()
group by
o.Account_ID ) as PreQualified
JOIN Accounts a
on PreQualified.Account_ID = a.Account_ID
Join Contact C
on a.Account_ID = c.Account_ID
JOIN Sales_Reps sr
ON a.sales_rep_id = sr.sales_rep_id
If you want to count records use
count(*)
Instead of
count(o.order_id)

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

Mysql JOIN two nested queries

In my query below, i am trying to join one result set to another using the customerNumber identifier. I want to find each customer's amount ordered and the amount paid. The sql does not execute with no help from Navicat Client
SELECT DISTINCT tabl1.customerNumber,
tabl1.amountOrdered, tabl2.amountPaid
FROM
(
SELECT Distinct c.customerNumber, o.orderNumber,
SUM(od.quantityOrdered * od.priceEach) amountOrdered
FROM ClassicModels.Customers c
INNER JOIN ClassicModels.Orders o
ON c.customerNumber = o.customerNumber
INNER JOIN ClassicModels.OrderDetails od
ON o.orderNumber = od.orderNumber
GROUP BY od.orderNumber
ORDER BY c.customerNumber
) tabl1
INNER JOIN
(
SELECT DISTINCT c.customerNumber, p.amount amountPaid
FROM ClassicModels.Customers c
INNER JOIN ClassicModels.Payments p
ON c.customerNumber = p.customerNumber
) tabl2 ON tabl1.customerNumber = tabl2.customerNumber
If you want to select each customer's amount ordered and amount paid, this much simpler query should work:
SELECT o.customerNumber as customerNumber,
SUM(od.quantityOrdered * od.priceEach) as amountOrdered,
SUM(p.amount) as amountPaid
FROM ClassicModels.Orders o
INNER JOIN ClassicModels.OrderDetails od
ON o.OrderNumber = od.OrderNumber
LEFT JOIN ClassicModels.Payments p
ON p.customerNumber = o.customerNumber
GROUP BY o.customerNumber