Reputation: 372
I am trying to find the maximum in count using group by
1st code:
SELECT MAX (COUNT (studid)) AS total,
unitcode,
semester,
TO_CHAR (ofyear, 'yyyy') AS "Year of Offer"
FROM uni.enrolment
WHERE TO_CHAR (ofyear, 'YYYY') = '2013'
GROUP BY semester, ofyear, unitcode
ORDER BY total;
Results:
ORA-00937: not a single-group group function 00937. 00000 - "not a single-group group function" *Cause:
*Action: Error at Line: 18 Column: 36
2nd code:
SELECT unitcode,
TO_CHAR (ofyear, 'YYYY') AS year,
semester,
COUNT (studid) AS student_count
FROM uni.enrolment
GROUP BY unitcode, ofyear, semester
HAVING COUNT (studid) = ( SELECT MAX (COUNT (studid))
FROM uni.enrolment
GROUP BY unitcode, ofyear, semester
HAVING TO_CHAR (ofyear, 'YYYY') = '2013')
ORDER BY unitcode;
Results:
╔════════════════════════════════════════════════╗
║ UNITCODE YEAR SEMESTER STUDENT_COUNT ║
╠════════════════════════════════════════════════╣
║ EG2004 2013 1 8 ║
╚════════════════════════════════════════════════╝
When I run the 1st code it gives me an error but the 2nd code works perfect. I don't really understand the error. Why do I have to use a subquery to solve it?
Upvotes: 0
Views: 57
Reputation: 1270181
The nested aggregation functions are an Oracle-ism. I personally find them rather confusing. But MAX(COUNT( . . . ))
is the same as:
select max(cnt)
from (select . . . , count(<something>) as cnt
from t
group by . . .
) x;
That is, it does two aggregations, one with a group by
and one without. The outer one cannot return unaggregated columns. That is why you are getting an error.
I want to note that for your second query, you need to filter on year both inside and outside. So the query might happen to return correct results, but you want to do:
SELECT unitcode, TO_CHAR(ofyear, 'YYYY') AS year, semester,
COUNT(studid) AS student_count
FROM uni.enrolment
WHERE TO_CHAR(ofyear, 'YYYY') = '2013')
GROUP BY unitcode, TO_CHAR(ofyear, 'YYYY'), semester
HAVING COUNT(studid) = (SELECT MAX (COUNT (studid))
FROM uni.enrolment
GROUP BY unitcode, ofyear, semester
HAVING TO_CHAR(ofyear, 'YYYY') = '2013'
)
ORDER BY unitcode;
Notice that I also put the expression in the GROUP BY
for year
. You want to aggregate by the year, not by the original date.
Upvotes: 1
Reputation: 35603
You need to calculate the counts before you can determine which of those is the maximum or equal maximum. I suggest using RANK() OVER()
or DENSE_RANK() OVER()
for the second step; where the result of this equal 1 (when ordered DESC) you have the largest count. In this query the windowing function will be processed after the GROUP BY
as part of the SELECT
clause (the select clause is NOT the first processed) hence the COUNT() is available as an input for the ranking.
SELECT
total
, unitcode
, semester
, ofyear
FROM (
SELECT
count(studid) AS total
, unitcode
, semester
, to_char(ofyear, 'yyyy') AS "Year of Offer"
, dense_rank() OVER (ORDER BY count(studid) DESC) AS rnk
FROM uni.enrolment
WHERE to_char(ofyear, 'YYYY') = '2013'
GROUP BY
semester
, ofyear
, unitcode
) d
WHERE rnk = 1 --<< this is how we only list the maximum(s)
ORDER BY
unitcode
, semester
;
note also you could use EXTRACT(YEAR FROM ofyear)
instead of using to_char
Upvotes: 0