Search code examples
sqlms-accessms-access-2010ms-access-2016

Display product with minimum units sold in 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

SQL DataBase


Solution

  • 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).