【问题标题】:min(count()) function not workingmin(count())函数不起作用
【发布时间】:2017-08-12 17:00:52
【问题描述】:

我想显示学生人数最少的部门的名称。这是我的查询:

select department_name, count(student_id)
from   department d, student s
where  d.department_id = s.department_id
group by department_name;

此查询工作正常并显示学生人数,但是当我将 min 函数添加为 min(count(student_id)) 时,它会失败:

第 1 行出现错误:ORA-00937:不是单组组函数

我不知道我做错了什么。有什么帮助/建议吗?

【问题讨论】:

  • 你不能这样做,因为count(student_Id)是在分组department之后完成的。对于min,您需要拥有多个记录。
  • 多条记录是什么意思?我不明白。

标签: sql oracle


【解决方案1】:

正如其他人所指出的那样,当您将计数包装在 MIN 中时,就会得到 min PER DEPARTMENT。因为每个部门已经只有一行,所以这是非操作

你说你想要的是所有部门的分钟。像这样的:

Select department_name from(
 select department_name, count(student_id), rank() over(order by count(student_id)) as x
 from   department d, student s
 where  d.department_id = s.department_id
 group by department_name
)
Where x = 1

它是如何工作的? rank() 函数按顺序为行分配位置,就像赢得比赛一样。在这种情况下,顺序是学生的 count() 升序,因此最小计数位于位置 1。排名的特殊之处在于计数相同的行具有相同的排名。因此,我们知道排名为 1 的所有行都是同样的最小计数。为了只显示 =1 的行,我们必须使用子查询,唉(我知道你不想看到它)因为 oracle 不允许我们说像 where rank() over(...) =1 这样的东西。不过,子查询并不是真正的性能损失,因为排序是在对其余数据进行单次扫描的同时准备好的,然后通过外部 where 子句的过滤器。这与使用 HAVING 的其他已发布答案不同。在这种情况下,运行查询,找到所有计数,找到所有计数中的最小值,然后再次运行查询,再次找到计数,然后HAVING 将它们过滤到之前找到的最小值

【讨论】:

  • 感谢您的回复..!我刚开始学习oracle sql(已经1天了)。所以我可能需要一段时间才能理解所有内容。
  • 我为您添加了一些解释.. 我对您的查询的主要补充是 rank() ... as x 完成了艰苦的工作。如果您正在学习 SQL,请注意,请永远不要像旧的 oracle 语法 FROM table1, table2 WHERE table1.id = table2.id 那样编写查询,始终像 FROM table1 INNER JOIN table2 ON table1.id = table2.id 那样编写查询。如果您从未使用过 JOIN 关键字语法,请查看有关内部和左/右/全外连接的一些教程
  • 好的。谢谢你..!
【解决方案2】:

在这种情况下,MIN() 函数在 GROUP BY 函数之前起作用。所以错误来了。你可以试试这个。

SELECT TOP 1 department_name,count(student_id) as A
FROM department d,student s 
WHERE d.department_id=s.department_id 
GROUP BY department_name
ORDER BY A DESC

【讨论】:

  • 感谢您的回复。问题是这个查询只会显示一行,但如果两行具有相同的值怎么办。我需要显示具有最小值的所有行。
  • 她还为 Oracle 标记了这个问题。
【解决方案3】:

如果我理解正确,您需要找到学生人数最少的部门。下面的查询可以给你答案。

select department_name
from   department d, student s
where  d.department_id = s.department_id
group by department_name
having count(student_id) = (select min(a.cnt_std_id) from (select 
department_name, count(student_id) cnt_std_id
from   department d, student s
where  d.department_id = s.department_id
group by department_name)a);

【讨论】:

  • 谢谢它的工作......但是有没有其他方法可以在不使用子查询的情况下实现它?
  • 窗口函数可以简化这一点,并提高性能 - 请参阅我的答案。您仍然需要一个子查询,因为 oracle 不允许我们在 where 子句或 have 子句中编写窗口函数,但这个答案与我的关键区别在于,这个答案准备了两次结果集,而使用窗口函数准备只有一次。
【解决方案4】:

这是另一种方式:

select department_name, students
from   ( select department_name, count(*) as students
              , rank() over (order by count(*)) as seq
         from   department join student using(department_id)
         group by department_name )
where seq = 1;

【讨论】:

  • 看起来很眼熟:)
【解决方案5】:

这是一个简单的方法。祝你好运

SELECT department_name, MIN(A)
FROM (select department_name, count(student_id) as A
from   department d, student s
where  d.department_id = s.department_id
group by department_name)

【讨论】:

    猜你喜欢
    • 2014-12-19
    • 2014-08-04
    • 2013-07-15
    • 2021-08-26
    • 2023-03-26
    • 1970-01-01
    • 2015-09-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多