如何最大限度地正确使用group by?

How to use group by correctly in maximum?

我正在尝试使用 group by

找到计数的最大值

第一个代码:

 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: not a single-group group function 00937. 00000 - "not a single-group group function" *Cause:
*Action: Error at Line: 18 Column: 36

第二个代码:

  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             ║
╚════════════════════════════════════════════════╝

当我 运行 第一个代码时,它给我一个错误,但第二个代码完美无缺。我真的不明白这个错误。为什么一定要用子查询来解决呢?

您需要先计算计数,然后才能确定其中的最大值或等于最大值。我建议在第二步使用 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

嵌套聚合函数是 Oracle 主义。我个人觉得他们相当混乱。但是 MAX(COUNT( . . . )) 等同于:

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

也就是说,它进行两种聚合,一种带有 group by,一种不带。外部不能 return 未聚合列。这就是您收到错误的原因。

我要注意,对于您的第二个查询,您需要过滤内部和外部的年份。所以查询可能恰好return正确的结果,但是你想做的是:

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;

请注意,我还将 year 的表达式放在 GROUP BY 中。您希望按年份而不是原始日期进行汇总。