Как правильно использовать группу по максимуму? - PullRequest
0 голосов
/ 21 мая 2018

Я пытаюсь найти максимальное количество при использовании группы по

1-й код:

 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;

Результаты:

ORA-00937: негрупповая функция для одной группы 00937. 00000 - «не групповая функция для одной группы» * Причина:
* Действие: Ошибка в строке: 18 Колонка: 36

2-й код:

  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;

Результаты:

╔════════════════════════════════════════════════╗
║ UNITCODE    YEAR     SEMESTER    STUDENT_COUNT ║
╠════════════════════════════════════════════════╣
║ EG2004      2013     1           8             ║
╚════════════════════════════════════════════════╝

Когда я запускаю 1-й код, он выдает ошибку, но 2-й код работает отлично.Я не очень понимаю ошибку.Почему я должен использовать подзапрос, чтобы решить это?

Ответы [ 2 ]

0 голосов
/ 21 мая 2018

Вложенные функции агрегации - это Oracle-ism.Я лично нахожу их довольно запутанными.Но MAX(COUNT( . . . )) - это то же самое, что и:

select max(cnt)
from (select . . . , count(<something>) as cnt
      from t
      group by . . .
     ) x;

То есть он выполняет две агрегации: одну с group by и одну без.Внешний не может возвращать неагрегированные столбцы.Вот почему вы получаете сообщение об ошибке.

Хочу заметить, что для второго запроса вам нужно отфильтровать по году как внутри, так и снаружи.Поэтому запрос может вернуть правильные результаты, но вы хотите сделать:

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;

Обратите внимание, что я также поместил выражение в GROUP BY для year.Вы хотите агрегировать по году, а не по исходной дате.

0 голосов
/ 21 мая 2018

Вам необходимо рассчитать количество, прежде чем вы сможете определить, какой из них является максимальным или равным максимуму.Я предлагаю использовать RANK() OVER() или DENSE_RANK() OVER() для второго шага;где результат равен 1 (при заказе DESC) у вас самый большой счет.В этом запросе оконная функция будет обработана после GROUP BY как часть предложения SELECT (предложение select НЕ обрабатывается первым), поэтому COUNT () доступен в качестве входных данных для ранжирования.

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
;

обратите внимание, что вы можете использовать EXTRACT(YEAR FROM ofyear) вместо to_char

...