Display product with minimum units sold in SQL - sql

I've been tasked with the following Query to design:
"Out of the products that sold units in 2019 (that is, that sold at least one unit), we want to know the product that sold the least number of units. Your table must show:
 Product ID
 Product name
 Product’s category name "
I have included a screenshot of the database.
I am, in fact, able to retrieve the value corresponding to the minimum units sold [95 in this case], but cannot also display the corresponding product name to that value in MS Access.
Using the following code displays the correct minimum value:
SELECT MIN(UnitsSold)
FROM
(SELECT Products.ProductID, ProductName, Categories.CategoryID, CategoryName, SUM(Quantity) AS UnitsSold
FROM Orders, OrderDetails, Products, Categories
WHERE Orders.OrderID = OrderDetails.OrderID AND OrderDetails.ProductID = Products.ProductID And Products.CategoryID = Categories.CategoryID AND OrderDate BETWEEN #01/01/2019# AND #12/31/2019#
GROUP BY Products.ProductID, ProductName, Categories.CategoryID, CategoryName
HAVING SUM(Quantity) >= 1);
But when I try to also display that product with this modification:
SELECT MIN(UnitsSold, Products.ProductID, ProductName
FROM
(SELECT Products.ProductID, ProductName, Categories.CategoryID, CategoryName, SUM(Quantity) AS UnitsSold
FROM Orders, OrderDetails, Products, Categories
WHERE Orders.OrderID = OrderDetails.OrderID AND OrderDetails.ProductID = Products.ProductID And Products.CategoryID = Categories.CategoryID AND OrderDate BETWEEN #01/01/2019# AND #12/31/2019#
GROUP BY Products.ProductID, ProductName, Categories.CategoryID, CategoryName
HAVING SUM(Quantity) >= 1);
I am met with the error:
Your query does not include the specified expression 'ProductID' as part of an aggregate function

Why not just use ORDER BY and TOP 1?
SELECT TOP (1)
p.ProductID,
ProductName,
c.CategoryName,
FROM
Orders o
INNER JOIN OrderDetails od ON o.OrderID = od.OrderID
INNER JOIN Products p ON od.ProductID = p.ProductID
INNER JOIN Categories c ON p.CategoryID = c.CategoryID
WHERE OrderDate BETWEEN #01/01/2019# AND #12/31/2019#
GROUP BY
p.ProductID,
ProductName,
c.CategoryName
HAVING SUM(Quantity) >= 1
ORDER BY SUM(Quantity) DESC
Notes:
always use explicit joins (with the ON keyword) instead of implicit joins (with commas in the FROM clause), whose syntax is harder to follow and has fallen out of favor more than 20 years ago
table aliases make the query easier to write and read; also, in a multi-table query, you want to qualify all column names (there are a few table prefixes missing in your query).

Related

How do carry out arithmetic functions using join in SQL?

Products
productid
productname
unitprice
1
potato
5
OrderDetails
ordered
productid
unitprice
discount
1
1
5
.15
I am trying to list all products using the highest price (which would be without the discount). So I need to calculate the price without the discount and list that as unitprice alongside the productid and productname.
SELECT products.productid, products.productname, orderdetails.unitprice
FROM products
INNER JOIN orderdetails ON products.productid = orderdetails.productid
WHERE orderdetails.unitprice =
(SELECT (orderdetails.unitprice/( 1- orderdetails.discount))
AS highest_unitprice
FROM orderdetails);
I get this error:
single-row subquery returns more than one row
How can I fix this?
Maybe this will compile->
SELECT *
FROM
(
SELECT products.productid, products.productname, orderdetails.unitprice,
ROW_NUMBER()OVER(PARTITION BY orderdetails.productid ORDER BY orderdetails.unitprice) AS PriceIndex
FROM products
INNER JOIN orderdetails ON products.productid = orderdetails.productid
)AS X
WHERE
PriceIndex=1

Trying to get product(s) that have been ordered the least amount of times

I want to find out the products that have been ordered the least amount of times without using order by desc or top 1 etc. My query seems to get the min calculation right but the productID and name don't match
SELECT T.ProductID, ProductName, MIN(Total_Quantity)
FROM (SELECT ProductID, SUM(Quantity) as Total_Quantity
FROM orderdetails
GROUP BY orderdetails.ProductID) as T
JOIN products p on T.ProductID = p.ProductID
my code is pasted above and this is the output:
Total Minimum Qty Output
Here is the sum of quantity per product ordered
Total Qty per product
I want to find out the products that have been ordered the least amount of times
This sounds like group by and having:
select p.productid, p.productname, sum(od.total_quantity) as total_quantity
from products p
left join orderdetails od on od.productid = p.productid
group by p.productid
having sum(od.total_quantity) > 3

Stuck doing a common table expression to calculate total orders for each product category using NORTHWND

Guys so as part of my job as a Data Support Analyst I am training up to become a software developer, my mentor gave me a group of test statements and this one seems way more advanced than anything I have done previously. The question is...
*
6) Write a subquery or common table expression to calculate total
orders for each product category. that will Write a query that will
bring back each product name, the total number of orders made for the
product and join to the subquery or CTE to calculate the percentage
of sales that product represents of its product category. For example,
if Category of Soaps has 2 products; Blue Soup and Red Soap, blue soup
had 40 orders and red soaps had 10 orders I would expect to see the
following rows: Product Name Total Orders % of Category Red
Soap 40 80%
Blue Soap 10 20%
*
So far I have managed to get the following but I'm struggling to progress past this...
;WITH [Products] (CategoryId, TotalNumberOfOrders)
AS (
SELECT p.CategoryId,
COUNT (OD.OrderID) as TotalNumberOfOrders
FROM [dbo].[Products] p
INNER JOIN [dbo].[Order Details] OD
ON p.ProductID=OD.ProductID
GROUP BY p.CategoryId )
SELECT * From Products
Any help would be fantastic! ( I'm using NORTHWND database btw)
I think what you need is
;WITH temp AS
(
SELECT p.CategoryId,
COUNT (DISTINCT OD.OrderID) as TotalNumberOfOrders
FROM [dbo].[Products] p
INNER JOIN [dbo].[Order Details] OD ON p.ProductID=OD.ProductID
GROUP BY p.CategoryId
)
SELECT p.ProductName,
Count(DISTINCT Od.OrderId) AS Total,
Count(DISTINCT Od.OrderId)*100/temp.TotalNumberOfOrders AS Percentage
FROM Products p
INNER JOIN [dbo].[Order Details] OD ON p.ProductId = OD.ProductId
INNER JOIN temp ON p.CategoryId = temp.CategoryId
GROUP BY p.ProductId, p.ProductName, temp.TotalNumberOfOrders
Remember Count(Distinct..) to count Order.
Using a sub-Query:
SELECT P.ProductName,
COUNT(OrderID) AS NumberOfOrders,
CAST((CAST(COUNT(OrderID) AS DECIMAL(9,2)) / CAST(Derived_Table.CNT AS
DECIMAL(9,2))) * 100 AS DECIMAL(9,2)) AS Percentage
FROM [Northwind].[dbo].[Order Details]
INNER JOIN dbo.Products AS P
ON [Order Details].ProductID = P.ProductID
INNER JOIN (SELECT COUNT(F.OrderID) AS CNT, P.CategoryID
FROM [Northwind].[dbo].[Order Details] F
INNER JOIN dbo.Products P
ON F.ProductID = P.ProductID
GROUP BY P.CategoryID) AS Derived_Table
ON P.CategoryID = Derived_Table.CategoryID
GROUP BY [Order Details].ProductID, P.ProductName, Derived_Table.CNT
ORDER BY [Order Details].ProductID

I want to find that how much number of products sold for particular category in northwind database?

I have three main Tables
categories:
categoryID(primary Key)
CategoryName
Description.
OrderDetails
OrderID (primary Key)
ProductID
Quantity
Products
productId (Primary Key)
ProductName
CategoryID
Now I have to write a query to get number of products sold for particular category?
here is my attempt
SELECT Products.ProductID,
Products.CategoryID,
SUM(OrderDetails.Quantity)
FROM Products
LEFT INNER JOIN OrderDetails
ON (SELECT OrderDetails.Quantity,
orderDetails.ProductID,
categories.categoryName
FROM orderDetails
LEFT INNER JOIN Categories
ON categories.categoryID=products.CategoryId
)
ON Products.ProductId = OrderDetaqils.ProductId
i am not getting any answer close to my requirement.its not correct
please give me the solution if possible
It would be great help if you can give me the solution. If you required any additional details please let me know
here is the SQL query
SELECT Product.ProductID,
sum(Quantity) as TotalSoldAmount,
categories.CategoryID,
CategoryName
FROM OrderDetails
-- INNER JOIN over all 3 Tables
INNER JOIN Product ON Product.ProductID = OrderDetails.ProductID
INNER JOIN categories ON categories.CategoryID = Product.CategoryID
-- we need to group our result because we used sum()
GROUP BY categories.CategoryID,
CategoryName,
Product.ProductID
and her the sqlfiddle as prove

How do I use SQL to select rows that have > 50 related rows in another table?

I've been trying to find out how to write this query in sql.
What I need is to find the productnames (in the products table) that have 50 or more orders (which are in the order table).
only one orderid is matched up to a productname at a time so when I try to count the orderid's it counts all of them.
I can get distinct productnames but once i add in the orderid's then it goes back to having multiple productnames.
I also need to count the number of customers (in the order table) that have ordered those products.
I need some serious help ASAP! if anyone could help me figure out how to figure this out that would be awesome!
Table: Products
`productname` in the form of a text like 'GrannySmith'
Table: Orders
`orderid` in the form of '10222'..etc
`custid` in the form of something like 'SMITH'
Assuming the orders table has a field that relates back to the products table named ProductId. The SQL would translate to:
SELECT p.ProductName, Count(*)
FROM Orders o
JOIN Products p
on o.ProductId = p.ProductId
GROUP BY p.ProductName HAVING COUNT(*) >= 50
The key is in the having component of the Group By clause. I hope this helps.
You might be missing an "Order Details" table - typically, an order has several order details, and each of the order details then maps to a product - something like the sample in Northwind:
In that case, your SQL query would be something like this: join the [Order Details] table to both the [Orders] and [Products] tables, group by the product ID and name, and count the OrderID's:
select
p.ProductID, p.ProductName, count(o.OrderID)
from
[order details] od
inner join
orders o on od.OrderID = o.OrderID
inner join
products p ON od.productID = p.ProductID
group by
p.ProductID, p.ProductName
having
count(o.OrderID) > 50