SQL query with w3schools db - sql

I should have asked multiple questions in my other post. Thanks to all who have helped, I am now stuck on another one..
Using the w3schools db, List SupplierID, SupplierName and ItemSupplied (count of number of items supplied by a supplier), sort the list first by number of items supplied (descending) and then by supplier name (ascending)
SELECT supplierid,
suppliername,
p.productname,
Count(s.supplierid) AS itemssupplied
FROM [Suppliers] AS s
INNER JOIN [Products] AS p
ON p.supplierid = s.supplierid
GROUP BY p.productid,
p.productname
ORDER BY Count (p.productid, p.productname) DESC
order BY s.suppliername
It's giving me an error, then again I am ordering by multiple ones. I think there's something I am not quite understanding here.
My other question is
List customers for each category and the total of order placed by that customer in a given category. In the query show three columnm: CategoryName, CustomerName, and TotalOrders (which is price * quantity for orders for a given customer in a given category). Sort this data in descending order by TotalOrders.
SELECT cg.CategoryName,
c.CustomerName,
Sum(p.Price * od.Quantity) AS TotalOrders
FROM [products] AS p
INNER JOIN [orderdetails] AS od
ON od.ProductID = p.ProductID
INNER JOIN [orders] AS o
ON o.OrderID = od.OrderID
INNER JOIN [customers] AS c
ON c.customerID = o.CustomerID
INNER JOIN [categories] AS cg
ON cg.CategoryID = p.CategoryID
GROUP BY c.CustomerName
ORDER BY TotalOrders DESC
Can someone please check if my query is correct? Thank you once again!

Question 1
You are really close but you only need to state ORDER BY once (also make sure to include all shown fields in your GROUP BY unless you are aggregating them):
SELECT SupplierID, SupplierName, p.ProductName, count(s.SupplierID) AS ItemsSupplied
FROM [Suppliers] AS s
INNER JOIN [Products] AS p ON p.SupplierID = s.SupplierID
GROUP BY p.ProductID, p.ProductName, SupplierID, SupplierName -- Added SupplierID, SupplierName
ORDER BY COUNT (p.productID, p.ProductName) DESC, s.SupplierName
Notice that you just place multiple sorts on the same line with a comma separating them.
Question 2
You're almost there but you need to group by any field that is not being aggregated. So in order not to get a parsing error, I added the cg.CategoryName to the GROUP BY line.
SELECT cg.CategoryName, c.CustomerName, Sum(p.Price*od.Quantity) AS TotalOrders
FROM [Products] AS p
INNER JOIN [OrderDetails] AS od ON od.ProductID = p.ProductID
INNER JOIN [Orders] AS o ON o.OrderID = od.OrderID
INNER JOIN [Customers] AS c ON c.customerID = o.CustomerID
INNER JOIN [Categories] AS cg ON cg.CategoryID = p.CategoryID
GROUP BY c.CustomerName, cg.CategoryName --Added CategoryName
ORDER BY TotalOrders DESC

You have several problems with the first query:
You're grouping by ProductID and ProductName even though you want the number of items supplied by a supplier, which means that you want to group by SupplierID and SupplierName.
You're supplying too many arguments to the COUNT function, which takes a single column name or *.
You've included a ProductName column in your results, which is not called for.
You need to ORDER BY both the number of products supplied and the SupplierName.
With those points in mind:
SELECT
s.SupplierID,
s.SupplierName,
COUNT(p.ProductID) AS ItemsSupplied
FROM
[Suppliers] AS s
INNER JOIN [Products] AS p ON p.SupplierID = s.SupplierID
GROUP BY
s.SupplierID, s.SupplierName
ORDER BY
ItemsSupplied DESC,
s.SupplierName ASC
Your second query is quite close, you're just missing one point, which is that you're looking for total of order placed by that customer in a given category. This means that in addition to grouping by c.CustomerName, you need to group by cg.CategoryID:
SELECT
cg.CategoryName,
c.CustomerName,
SUM(p.Price*od.Quantity) AS TotalOrders
FROM
[Products] AS p
INNER JOIN [OrderDetails] AS od ON od.ProductID = p.ProductID
INNER JOIN [Orders] AS o ON o.OrderID = od.OrderID
INNER JOIN [Customers] AS c ON c.customerID = o.CustomerID
INNER JOIN [Categories] AS cg ON cg.CategoryID = p.CategoryID
GROUP BY
c.CustomerName, cg.CategoryID
ORDER BY
TotalOrders DESC

The first one has two order by clauses
ORDER BY COUNT (p.productID, p.ProductName) DESC
and
ORDER BY s.SupplierName
also some databases will complain when order by columns for queries using group by are not included in the selected columns

Related

Find Top 5 Customers for Beverages based on their total purchase value SQL

Here is the link to the Data Set.
https://www.w3schools.com/sql/trysql.asp?filename=trysql_asc
I have been trying to solve this but couldn't find a way to get the total purchase value while grouping with the customer table
I would recommend using a Common Table Expression (CTE) as, in my experience, it helps with scalability/maintenance down the road and easily enables you to see what the data is under the hood if you wanted to simply run the CTE itself.
I join the Customer to the Order to get the OrderID
I join the Order to OrderDetails to get the ProductID and Order Quantity
I join the OrderDetails to Products to get the Price
I join the Categories to filter for just Beverages
All this is wrapped as a CTE (similar to a subquery), on top of which I can now aggregate at the Customer level and sequence by Order Value in a descending fashion.
with beverage_orders_cte as(
SELECT c.CustomerName, o.OrderID
, od.OrderDetailID, od.ProductID, od.Quantity
, p.ProductName, p.Price
, od.Quantity * p.Price as OrderVal
,cat.CategoryName FROM Customers c
inner join Orders o
on c.CustomerID = o.CustomerID
inner join OrderDetails od
on o.OrderID = od.OrderID
inner join Products p
on od.ProductID = p.ProductID
inner join Categories cat
on p.CategoryID = cat.CategoryID and cat.CategoryID = 1
)
select CustomerName, SUM(OrderVal) as Revenue
From beverage_orders_cte
Group by CustomerName
Order by Revenue desc
Limit 5
Hope this helps, good luck.
Something like that?
SELECT c.customerid,
Sum(p.price)
FROM customers AS c
INNER JOIN orders AS o
ON o.customerid = c.customerid
INNER JOIN orderdetails AS od
ON od.orderid = o.orderid
INNER JOIN products AS p
ON p.productid = od.productid
GROUP BY c.customerid
ORDER BY Sum(p.price) DESC
LIMIT 5
Just following on from your quantity comment...
SELECT c.customerid,
Sum(p.price),
Sum(p.price * od.quantity)
FROM customers AS c
INNER JOIN orders AS o
ON o.customerid = c.customerid
INNER JOIN orderdetails AS od
ON od.orderid = o.orderid
INNER JOIN products AS p
ON p.productid = od.productid
GROUP BY c.customerid
ORDER BY Sum(p.price) DESC
LIMIT 5
I think this is the best optimized code.
Please try with this.
SELECT CustomerID, Count(Quantity * Price) AS Total
FROM Orders, OrderDetails, Products
Where Orders.OrderID = OrderDetails.OrderID AND Products.ProductID = OrderDetails.ProductID
Group by CustomerID
ORDER BY Total DESC
LIMIT 5

sql use aggregate function that counts a unique value with group by using inner joins

I searched and found similar questions online but not my particular one, they all use where or having clause.If theres one similar to mine please link it. It's a 2 part question and I have the first one done. Thank you in advance.
Okay so heres the question, part 1
"Find by customer, the total cost and the total discounted cost for each product on the order ?".
It also asks to use inner joins to find the customer and order it a specific way. Below is the answer.
SELECT
C.companyname, O.orderid, O.orderdate, P.productname,
OD.orderid, OD.unitprice, OD.qty, OD.discount,
(OD.unitprice * OD.qty - (OD.qty * OD.discount)) AS TotalCost,
(OD.qty * OD.discount) AS TotalDiscountedCost
FROM
Sales.Customers AS C
INNER JOIN
Sales.Orders AS O ON C.custid = O.custid
INNER JOIN
Sales.OrderDetails OD ON O.orderid = OD.orderid
INNER JOIN
Production.Products as P ON OD.productid = P.productid
ORDER BY
C.companyname, O.orderdate;
Now the second question is to
follow up and resume the first one by "customer and the order date year, the total cost and the total discounted cost on the order ?". It also asks for this, "Project following columns in the select clause as.
GroupByColumns.companyname
GroupByColumns.OrderdateYear
AggregationColumns.CountNumberOfIndividualOrders
AggregationColumns.CountNumberOfProductsOrders
AggregationColumns.TotalCost
AggregationColumns.TotalDiscountedCost
Finally to order by company name and orderdateYear( which are groups). Where im stuck is how to count the specific orders of qty that equal 1 as an aggregate function in the SELECT clause. I know it has to use the aggregate function COUNT because of the GROUP BY, just don't know how to. This is what I have.
SELECT
C.companyname, YEAR(O.orderdate) AS orderyear,OD.qty,
-- Where in the count function or if theres another way do I count all the
--single orders
--COUNT(OD.qty) AS indiviualorders,
(OD.unitprice * OD.qty - (OD.qty * OD.discount)) AS TotalCost,
(OD.qty * OD.discount) AS TotalDiscountedCost
FROM
Sales.Customers AS C
INNER JOIN
Sales.Orders AS O ON C.custid = O.custid
INNER JOIN
Sales.OrderDetails OD ON O.orderid = OD.orderid
INNER JOIN
Production.Products as P ON OD.productid = P.productid
GROUP BY
C.companyname, YEAR(O.orderdate)
ORDER BY
C.companyname, O.orderdate;
You case use a case statement inside a sum
SUM(CASE WHEN <xyz> THEN 1 ELSE 0 END)
But for the count of unique orders, use SELECT(DISTINCT ) on a key that is unique in the order table
SELECT COUNT(DISTINCT O.OrderID) As DistinctOrders FROM Table

SQL Practice: Multiple Order By

I'm doing some practice questions with my teacher's given answers.
what I have so far:
select Sup.supplierID, SupplierName, sum(OD.Quantity)
as ItemSupplied from Suppliers as Sup
inner join Products as P on Sup.SupplierID=P.SupplierID
inner join OrderDetails as OD on
P.ProductID=OD.ProductID
group by Sup.supplierID order by ItemSupplied DESC, SupplierName ASC;
What my teacher's answer look like (The one with SupplierID):
My problem is I'm not having the same answer as the teacher's.
Which part I got wrong?
I got it by changing sum() to COUNT(DISTINCT [ProductID from OrderDetails])
and ORDER BY this COUNT(DISTINCT [ProductID from OrderDetails]) in DESC first, then SupplierName in ASC:
select Sup.supplierID, SupplierName, count(DISTINCT OD.ProductID)
as ItemSupplied from Suppliers as Sup
inner join Products as P on Sup.SupplierID=P.SupplierID
inner join OrderDetails as OD on
P.ProductID=OD.ProductID
group by Sup.supplierID order by ItemSupplied DESC, SupplierName ASC;
I suspect your teacher is looking for a "count" of the products provided, as in the number of items in the catalog. Not a total quantity of items ordered. The specification isn't very clear.
SELECT s.supplierid
, s.suppliername
, COUNT(p.productid) AS cnt_items
FROM Products p
JOIN Suppliers s
ON s.supplierid = p.supplierid
GROUP
BY s.supplierid
, s.suppliername
ORDER
BY COUNT(p.productid) DESC
, s.suppliername ASC
If we want a count of items that have been ordered.. the number of products from a supplier that appear on at least one order...
SELECT s.supplierid
, s.suppliername
, COUNT(DISTINCT o.productid) AS cnt_items
FROM Products p
JOIN Suppliers s
ON s.supplierid = p.supplierid
JOIN OrderDetails o
ON o.productid = p.productid
GROUP
BY s.supplierid
, s.suppliername
ORDER
BY COUNT(DISTINCT o.productid) DESC
, s.suppliername ASC
You are missing SupplierName in your group by. The query should be failing.

How to Organize Multiple Joins SQL

In SQL, how should I be joining tables together when I do multiple joins in one query. Should I join on only one table - in this case the Customers table or is it okay to do what I have done (joining on different tables as new keys are needed)?
SELECT O.OrderID, O.OrderDate, C.City, C.Country, C.PostalCode, C.ContactName, O.CustomerID, O.ShipperID, D.ProductID, COUNT(D.ProductID) ProductCount, S.SupplierID
FROM Customers C
INNER JOIN Orders O
ON O.CustomerID = C.CustomerID
INNER JOIN OrderDetails D
ON O.OrderID = D.OrderID
INNER JOIN Products P
ON D.ProductID = P.ProductID
INNER JOIN Suppliers S
ON S.SupplierID = P.SupplierID
WHERE 1 = 1
GROUP BY O.OrderID
ORDER BY OrderDate DESC
I am using W3Schools SQL TryIt editor to test this, not sure what DB engine it is!
Thanks!
Of course you can join on multiple tables in a query. That is a big part of the power of SQL.
In your particular case, you don't need the join to the Suppliers table, because the column is already in Products.
Also, you need to be careful about your SELECT and GROUP BY clauses. In general, you should put all non-aggregated columns in the GROUP BY:
SELECT O.OrderID, O.OrderDate, C.City, C.Country, C.PostalCode, C.ContactName,
O.CustomerID, O.ShipperID, D.ProductID,
COUNT(D.ProductID) as ProductCount,
P.SupplierID
FROM Customers C INNER JOIN
Orders O
ON O.CustomerID = C.CustomerID INNER JOIN
OrderDetails D
ON O.OrderID = D.OrderID INNER JOIN
Products P
ON D.ProductID = P.ProductID
GROUP BY O.OrderID, O.OrderDate, C.City, C.Country, C.PostalCode, C.ContactName,
O.CustomerID, O.ShipperID, D.ProductID, P.SupplierId
ORDER BY OrderDate DESC;
The WHERE 1=1 is also unnecessary.
I wonder if this query really does what you want. However, you don't state what you actually want the query to do, so I'm merely speculating.
The way you have done it is find, don't forget that for each inner join, your record set may reduce by the number of non matching keys in each additional join.
you could also just use the JOIN syntax.

SQL Server : How to Select Sum Amount Spent for the Most Expensive Item by a Customer - Northwind DB

Actually question tells all; Lots of customers has many orders with for many items; I'm trying to display the total amount spent for the most expensive item ordered by that customers through the all orders given by that customer. I'm using Northwind DB and tables like Customers, Orders, Order Details, Products. I've the query below, I've tried to limit it by an aggregate function but SQL does not allow it on where clause. Any help?
select
p.ProductName,
c.ContactName,
od.ProductID,
MAX(od.UnitPrice)
SUM(od.UnitPrice*od.Quantity) as Total
from
Customers c
join
Orders o ON c.CustomerID = o.CustomerID
join
[Order Details] od on od.OrderID = o.OrderID
join
Products p on od.ProductID = p.ProductID
where
c.CustomerID in
group by
c.ContactName, p.ProductName, od.Quantity, od.ProductID
order by
MAX(od.UnitPrice) desc
I think the easiest way to solve this is by using a window function to get the highest priced product. The following query uses row_number() for this purpose:
select p.ProductName, c.ContactName, od.ProductID,
MAX(od.UnitPrice)
SUM(od.UnitPrice*od.Quantity) as Total
from Customers c join
(select od.*, o.CustomerId,
row_number() over (partition by o.CustomerId
order by od.UnitPrice desc) as seqnum
from [Order Details] od join
Orders o
on od.OrderId = o.OrderId
) od
on od.CustomerId = c.CustomerId and seqnum = 1 join
Products p
on od.ProductID = p.ProductID
group by c.ContactName, p.ProductName, od.ProductID
order by MAX(od.UnitPrice) desc;
Note that the joins have been rearranged a bit. You need the customer id to define the highest priced product in the subquery, so the subquery has the join to orders. You don't need the join in the outer query.