Reputation: 149
I'm trying to find the most ordered menu item in a table by counting the occurrences of their item id. I've tried a few different things but I'm pretty lost. This produced the error:
"An aggregate may not appear in the WHERE clause unless it is in a subquery contained in a HAVING clause or a select list, and the column being aggregated is an outer reference."
However I think it puts into perspective what I'm trying to achieve:
SELECT count(itemCode)
FROM OrderProcessing
WHERE count(itemCode)=max(count(itemCode))
Upvotes: 6
Views: 14282
Reputation: 5636
A where
clause that contains aggregation results is called a having
clause. However, you cannot nest aggregation functions: Max( Count( * )).
But you can layer them. The use of CTEs is good for this:
with
Data( ItemID )as(
select 1 union all
select 2 union all
select 2 union all
select 3 union all
select 3 union all
select 3
),
Sums( ItemID, TotalSold )as(
select ItemID, Count( * )
from Data
group by ItemID
)
select *
from Sums
where TotalSold =(
select Max( TotalSold )
from Sums );
This will show all items with the most transactions. However, due to the question this query is purported to be answering, I should think that showing all ties would be the correct result. If Items X and Y both sold the most, to submit Item X as the answer, then by implication all other items, including Item Y, sold less. That is not a correct answer. I would discuss this more with your analyst or whomever is asking for this result.
Upvotes: 2
Reputation: 16968
I use this query to find items that have highest occurrence:
SELECT t.*
FROM OrderProcessing t
JOIN
(SELECT itemCode, ROW_NUMBER() OVER (ORDER BY COUNT(*) DESC) seq
FROM OrderProcessing
GROUP BY itemCode) dt
ON t.itemCode= dt.itemCode
WHERE dt.seq = 1
And this query to find that count of highest occurrence:
SELECT MAX(cnt)
FROM (SELECT COUNT(*) cnt
FROM OrderProcessing
GROUP BY itemCode) dt
Upvotes: 2
Reputation: 1269913
If you want one row, I would suggest order by
:
SELECT TOP 1 itemCode, count(itemCode)
FROM OrderProcessing
GROUP BY itemCode
ORDER BY count(itemCode);
If you want all items with the maximum count, use WITH TIES
:
SELECT TOP 1 WITH TIES itemCode, count(itemCode)
FROM OrderProcessing
GROUP BY itemCode
ORDER BY count(itemCode);
If you want to be fancy, use window functions. Here is an example:
SELECT itemCode, cnt
FROM (SELECT itemCode, count(itemCode) as cnt,
MAX(count(itemCode)) OVER () as maxcnt
FROM OrderProcessing
GROUP BY itemCode
) op
WHERE cnt = maxcnt;
Upvotes: 5
Reputation: 35680
I. modified version of original query (UPDATE after @DanGuzman comment about ties)
select all items with the same count as most wanted item:
SELECT itemCode , count(*) as MaxCount
FROM OrderProcessing
GROUP BY itemCode
HAVING count(*) =
-- count of most wanted item
(select top 1 count(*)
from OrderProcessing
group by itemCode
order by count(*) desc)
II. the query to select one of most ordered items
SELECT top 1 itemCode --, count(*) as MaxCount --optional
FROM OrderProcessing
GROUP BY itemCode
ORDER BY count(*) DESC
Upvotes: 8
Reputation: 14077
This is another way of doing that:
SELECT OP.itemCode
FROM (
SELECT OP.itemCode, OP.TotalRows, MAX(TotalRows) OVER() AS MaxRows
FROM (
SELECT OP.itemCode, COUNT(*) AS TotalRows
FROM dbo.OrderProcessing AS OP
GROUP BY OP.itemCode
) AS OP
) AS OP
WHERE OP.TotalRows = OP.MaxRows;
It doesn't look very pretty, but it could result in better execution plan (sort is a really resource-hungry clause).
It also should return you results even if there's more than one Menu Item with same occurence.
Upvotes: 2