SQL query MAX() function - sql

select ProductID,ProductName,QuantityPerUnit
from Products
where Products.UnitPrice=Max(UnitPrice)
What is wrong in this query?
I had tried 'having' in place of 'where' tag.
select ProductID,ProductName,QuantityPerUnit
from Products
having Products.UnitPrice=Max(UnitPrice)
it must produce result with max unit price,
ProductID ProductName QuantityPerUnit
38 Côte de Blaye 12 - 75 cl bottles

If you want the product(s) with the maximum UnitPrice:
select ProductID,ProductName,QuantityPerUnit
from Products
where UnitPrice = (select Max(UnitPrice) from Products)
This query:
select Max(UnitPrice) from Products
returns the maximum UnitPrice.
If there are more than 1 products with that price, they will all be returned.
If you want just 1, you can use LIMIT 1 or TOP 1, depending on the rdbms you use.

You cannot simply use aggregate function in a where clause unless it's in a subquery.
Try :::
select ProductID,ProductName,QuantityPerUnit from Products
Where Products.UnitPrice= (select Max(UnitPrice) from Products)
If you're using TSQL, then better use
select top 1 With ties ProductID,ProductName,QuantityPerUnit from Products
Order by UnitPrice desc
This will give you all the products with highest unit price and is efficient since there's no subquery.

Use sub query to find max price
SELECT ProductID, ProductName, QuantityPerUnit
FROM Products
WHERE UnitPrice = (SELECT Max(UnitPrice) FROM Products)

can use HAVING clause
SELECT ProductID, ProductName, QuantityPerUnit FROM Products
GROUP BY ProductID, ProductName, QuantityPerUnit
HAVING UnitPrice = MAX(UnitPrice)

What is wrong with your query is that you are mixing aggregation value with raw values in the query.
If you want only one row, I would recommend a different approach:
select ProductID, ProductName, QuantityPerUnit
from Products
order by UnitPrice desc
fetch first 1 row only;
Although fetch first is standard SQL, not all databases support it, so you may need the appropriate syntax for your database.

What I tried is:
Select Max(UnitPrice) From Products
select Max(UnitPrice) ProductID,ProductName,QuantityPerUnit
from Products
Group By ProductID,ProductName,QuantityPerUnit having Max(UnitPrice)>200

Related

How to use SUM and MAX on the same column?

So I'm having an SQL table where I will need find out the product that has been purchased the most meaning that I need to do a SUM and a group by on all the quantity of the products:
SELECT PRODUCT_ID, SUM(QUANTITY) FROM PURCHASE GROUP BY PRODUCT_ID
However when I try to find the product with the maximum amount of purchases it gives me an error:
SELECT MAX(QUANTITY) FROM(SELECT PRODUCT_ID, SUM(QUANTITY) FROM PURCHASE GROUP BY PRODUCT_ID)
Any ideas?
Just order by and keep the top record only:
SELECT PRODUCT_ID, SUM(QUANTITY) SUM_QUANTITY
FROM PURCHASE
GROUP BY PRODUCT_ID
ORDER BY SUM_QUANTITY DESC
LIMIT 1
The actual syntax might vary accross RDBMS. The above would work in MySQL and Postgres.
In SQL Server, you would use SELECT TOP (1) ... ORDER BY SUM_QUANTITY DESC.
In Oracle >= 12c, you would use SELECT ... ORDER BY SUM_QUANTITY DESC FETCH FIRST ROW ONLY.
You also have to consider the possibilty of ties in the first position, for which there are different strategies depending on your requirement and RDBMS.

SQL query can't use variable in FROM statement

I'm new to SQL, so sorry for maybe stupid question.
Table will be from this SQL sandbox:
https://www.w3schools.com/sql/trysql.asp?filename=trysql_asc
There is table of format
OrderDetailID OrderID ProductID Quantity
1 10248 11 12
2 10248 42 10
3 10248 72 5
4 10249 14 9
5 10249 51 40
I want to get products with maximum average quantity.
I can get this using the following query:
SELECT avg.ProductID, avg.Quantity
FROM (
SELECT ProductID, AVG(Quantity) Quantity
FROM OrderDetails
GROUP BY ProductID
) avg
WHERE avg.Quantity = (
SELECT MAX(Quantity) FROM (
SELECT ProductID, AVG(Quantity) Quantity
FROM OrderDetails
GROUP BY ProductID
)
)
ProductID Quantity
8 70
48 70
Here I twice use block
SELECT ProductID, AVG(Quantity) Quantity
FROM OrderDetails
GROUP BY ProductID
because if I use query with avg instead of second block
SELECT avg.ProductID, avg.Quantity
FROM (
SELECT ProductID, AVG(Quantity) Quantity
FROM OrderDetails
GROUP BY ProductID
) avg
WHERE avg.Quantity = (SELECT MAX(Quantity) FROM avg)
I get error could not prepare statement (1 no such table: avg)
So my question is:
Is it a kind of syntaxis mistake and could be simply corrected, or for some reason I can't use variables like that?
Is there simplier way to make the query I need?
Consider Common Table Expressions (CTE) using WITH clause which allows you to avoid repeating and re-calculating the aggregate subquery. Most RDBMS's supports CTEs (fully valid in your SQL TryIt linked page).
WITH avg AS (
SELECT ProductID, AVG(Quantity) Quantity
FROM OrderDetails
GROUP BY ProductID
)
SELECT avg.ProductID, avg.Quantity
FROM avg
WHERE avg.Quantity = (
SELECT MAX(Quantity) FROM avg
)
This is not really a syntax thing, this is rather scope: you try to
reference an alias where it is not in a parent-child relationship. Only this way they can reference each other. (The identifier there is an alias not a variable - that's a different thing.)
A simpler way is to create a temporary set before you run the filter condition - as in a previous answer, with a CTE, or you can try with a temp table. These can be used anywhere because their scope is not within a subquery.

Sorting results of aggregate function

This code:
SELECT ProductID, COUNT(ProductID) AS Occurrences
FROM OrderDetails
Group By ProductID;
is my attempt to take the productIDs that occur in an orderDetails table, count how many orders contain that product, and then sort the productID counts descending. In layman's terms, I want to show which products are the most popular, by showing their count in descending order so that the products that "sold" the most will occur at the top. The issue I have is that when I tried to use "Group by" with "Occurrences", it spat out an error that I cannot use aggregate functions with group by. If I group by ProductID, it shows the counts all over the place, which isn't the most useful way to present the information.
This should work:
SELECT ProductID, COUNT(ProductID) AS Occurrences
FROM OrderDetails
Group By ProductID
Order By COUNT(ProductID) DESC;
What you really want to use if you want to know the popularity of the products is SUM not COUNT:
SELECT ProductID,
sum(Qty) AS Occurrences
FROM OrderDetails
Group By ProductID
Order By sum(Qty) DESC;
COUNT will give you interesting results. Or you could use count of orders like this:
select ProductID
count(distinct OrderNumber) as NumberOfOrders
from OrderDetails
group by ProductID
order by count(distinct OrderNumber) desc;

how to match a value with SQL max(count) function?

I have a orderLine table looks like this
I would like to know which pizza is the best seller, and the quantity of pizza sold.
I've tried query:
select sum(quantity), pizza_name from order_line group by pizza_name;
it returns
which is almost what I want, But when I start adding Max function, it could not match the pizza name with the total quantity of pizza sold
For example:
select MAX(sum(quantity)), pizza_name from order_line group by pizza_name;
it returns following error:
"not a single-group group function"
I guess I could achieve this by using a sub-query, but I have no idea how to do this.
You don't need max for this. If you only want one pizza, then you can use order by and fetch first 1 row only (or something similar such as limit or top):
select sum(quantity), pizza_name
from order_line
group by pizza_name
order by sum(quantity)
fetch first 1 row only;
Or, if you want all such pizzas, use rank():
select p.*
from (select sum(quantity) as quantity, pizza_name,
rank() over (order by sum(quantity) desc) as seqnum
from order_line
group by pizza_name
) p
where seqnum = 1;
Both of the queries give the same desired result
SELECT PIZZA_NAME,
SUM(QUANTITY) "Total Quant"
FROM Order_line
GROUP BY PIZZA_NAME
ORDER BY "Total Quant" DESC
FETCH FIRST 1 row only;
SELECT PIZZA_NAME, "Total Quantity" FROM (
SELECT PIZZA_NAME,SUM(QUANTITY) "Total Quantity", RANK() OVER (ORDER BY SUM(QUANTITY) DESC) T FROM Order_line GROUP BY PIZZA_NAME
) query1 where query1.T=1 ;
You group by pizza_name to get sum(quantity) per pizza_name.
Then you aggregate again by using MAX on the quantity sum, but you don't specify which of the three pizza names to have in the result. You need an aggregate function on pizza_name as well, which you don't have. Hence the error.
If you want to use your query, you must apply the appropriate aggregation function on pizza_name, which is KEEP DENSE_RANK FIRST/LAST.
select
max(sum(quantity)),
max(pizza_name) keep (dense_rank last order by sum(quantity))
from order_line
group by pizza_name;
But on one hand Gordon's queries are more readable in my opinion. And on the other this double aggregation is Oracle specific and not SQL standard. Unexperienced readers may be confused that the query produces one result row in spite of the GROUP BY clause.

Counting records in a table given corresponding ID

This seems like such an easy query to run yet I cannot get it to work and I'm starting to rethink why I chose to tackle this project.
I am trying to find how many records are in a table where an id is identical. For example
select productid, productgroup, shelflvl, shelfaisle, Count(Shelfaisle) AS totalaisles
from productlocation
Where productid= productid AND productgroup = 'canned'
Group By productid, productgroup, shelflvl, shelfaisle
A product with the same id can be in a different aisle and on a different shelflvl. All I am trying to do is see how many aisles a product is in and I cannot for the life of me get it to work properly.
Any help is appreciated thank you!
I'm assuming a product cannot belong to many productgroups.
Remove Shelfaisle from GROUP BY as this is what you're trying to count.
Also, a COUNT(DISTINCT Shelfaisle) would prevent duplicates (if applicable).
Lastly, you don't need a productid=productid condition which apparently always yields true.
Cut a long story short:
select
productid, productgroup, shelflvl, Count(distinct Shelfaisle) AS totalaisles
from productlocation
Where productgroup = 'canned'
Group By productid, productgroup, shelflvl
Don't group by the column you are trying to aggregate:
select productid, productgroup, Count(Shelfaisle) AS totalaisles
from productlocation
Where productid=productid AND productgroup = 'canned'
Group By productid, productgroup
How about:
select productid, productgroup, Count(shelfaisle) AS totalaisles
from productlocation
Where productid= productid AND productgroup = 'canned'
Group By productid,productgroup
You are adding in additional columns to group by, which means that you can't isolate the product as the thing to count. You are counting products on specific rows on specific shelflevels, when you only need the product and shelfaisle.
This would work:
SELECT productid, shelflvl, MIN(productgroup) AS productgroup,
COUNT(Shelfaisle) AS totalaisles
FROM productlocation
WHERE productgroup = 'canned'
GROUP BY productid, shelflvl
ORDER BY productid;