oracle 分组函数里可以嵌套吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle 分组函数里可以嵌套吗?相关的知识,希望对你有一定的参考价值。

select deptno,sum(select sal from emp where job='SALESMAN') from emp group by deptno;

例如这样 在sum里嵌套,不可以吗?
我试了我那样写不可以~可是子查询不就是一个结果吗,不是说可以当任何数用吗?我是不理解为什么不可以

  可以 ,但最多只能两层。

  Oracle分组与组函数
  
  一、求和与求平均
  1、什么是组函数
  组函数就是我们前面我说过的多行函数。它主要针对表进行操作。因为只有表中,才有多行数据。下面我们以SUM和AVG这两个组函数为例,先从它们开始,介绍组函数的特性。 www.2cto.com
  2、SUM 求和函数
  gyj@OCM> select sum(salary) from t1;
  SUM(SALARY)
  -----------
  315888
  ORACLE在执行SUM()函数时,会从SALARY列取出每一行,把结果累加到一起。我们在讲单行函数和多行函数时就说过,对于单行函数,将列中每一行数据看作一个个体,单行函数分别对每个个体进行计算。而多行函数则把列中所有行数据看作一个整体,多行函数对这个整体中的所有元素,统一的做求和、求平均、统计最大或最小值等运算,无论此整体中包含多少行,最终返回的结果只有一个。一个总的和或平均值,或最大值,或最小值,等等。单行函数对每一行单独进行处理,每一行它都返回一个结果。
  gyj@OCM> select id,sum(salary) from t1;
  select id,sum(salary) from t1
  *
  ERROR at line 1:
  ORA-00937: not a single-group group function
  www.2cto.com
  这是很容易理解的,id(编号)列有10行数据,而SUM(salary)只有一行结果。一个10行,一个只有一行,Oracle没办法将这两个列组合在一起。列可以和单行函数组合使用,因为单行函数每一行都返回一个结果,列中有10行,就返回10个结果。如:
  gyj@OCM> select id,round(salary,1) from t1;
  ID ROUND(SALARY,1)
  ---------- ---------------
  2 8000
  3 10000
  4 15000
  5 0
  7 12000
  6 12000
  1 12000
  3、WHERE 条件 与组合函数
  在没有条件时,组合函数默认对列中所有行数据进行处理。我们可以使用条件,限制求和的行数。比如,我现在只想求一下姓名都为Joe的月薪的总和。
  gyj@OCM> select sum(salary) from t1 where name=\'Joe\';
  SUM(SALARY)
  -----------
  22000
  4、VAG求平均值
  AVG和SUM的用法完全相同,它是在SUM求后和,再除以行数,就得到一个平均值。例如:
  gyj@OCM> select avg(salary) from t1;
  AVG(SALARY)
  -----------
  17549.3333
  5、DISTINCT
  DISTINCT的俢作用是去除重复值,这我们在上一课有过描述。它也可以用在组函数中,下面我们看看效果:
  gyj@OCM> select sum(distinct salary) from t1;
  SUM(DISTINCTSALARY)
  -------------------
  162888
  6、NULL值的影响
  首先,对于SUM()函数来说,多了个NULL值不会有任何的影响。SUM()函数仅仅是忽略NULL值。
  gyj@OCM> insert into t1 values(26,\'rose\',null,null);
  1 row created.
  gyj@OCM> commit;
  Commit complete.
  gyj@OCM> select sum(salary) from t1;
  SUM(SALARY)
  -----------
  315888
  结果仍是315888。刚才没有添加NULL值前,求和的结果也是315888。
  对来求平均函数来说,它是先求和,再除以行数。那么,NULL值应不应该被计算进行数内呢。也就是说,现在salary列中有22行,其中有4行为NULL。求和的结果是315888,那么,在求平均时,是用总和数315888除以22呢,还是应该除以18。在默认情况下,是除以18。也就是说,ORACLE的组函数中,对于NULL值通常采取的都是不理不采,直接跳过,忽略它。我们来看一下求平均的结果:
  gyj@OCM> select avg(salary) from t1;
  AVG(SALARY)
  -----------
  17549.3333
  再来看看这个结果是不是315888除以18:
  gyj@OCM> select 315888/18 from dual;
  315888/18
  ----------
  17549.3333
  的确,是315888除以18。空值被简单的忽略了,就好像从来没有它
  但有时我们不能简单的忽略空。空值也是一行数据。它可能刚刚加入,还没有产生业绩等数据,但它也是一行数据。有时不能把他从行中剔除。这个时候,NVL()函数就派上用场了。先用NVL()函数,把空值转换为0,再进行组函数的计算,空值就不会被忽略了,使用形式如下:
  gyj@OCM> select avg(nvl(salary,0)) from t1;
  AVG(NVL(SALARY,0))
  ------------------
  14358.5455
  函数的嵌套,我们在前面也说过。也处理里层的函数,将处理结果传给外层,由外层处理。当遇到空值时,先由NVL将之转换为0,再由AVG()将0纳入到求平均的计算中。空会被AVG忽略,而0是不会被忽略的。
  下面再验证一下:
  gyj@OCM> select 315888/22 from dual;
  315888/22
  ----------
  14358.5455
  315888除以22,结果就是14358.5455。空值已经不被忽略了。
  
  二、最大值 MAX 与最小值 MIN
  在掌握前面两个函数的基础上,这两个函数的使用就非常简了。
  gyj@OCM> select max(salary),min(salary) from t1;
  MAX(SALARY) MIN(SALARY)
  ----------- -----------
  30000 0
  SALARY列中的最大值是30000,最小值是0。NULL值不算。组函数都会忽略NULL值。当然,我们可以使用NVL将空值转换为非空:
  gyj@OCM> select max(salary),min(nvl(salary,0)) from t1;
  MAX(SALARY) MIN(NVL(SALARY,0))
  ----------- ------------------
  30000 0
  
  三、COUNT 统计函数
  统计某列中满足条件行的数目。比如:
  gyj@OCM> select count(salary) from t1 where salary>5000;
  COUNT(SALARY)
  -------------
  17
  统计SALARY列大于5000的行的数目。COUNT(salary)括号中的salary列,可以换为* :
  gyj@OCM> select count(*) from t1 where salary>5000;
  COUNT(*)
  ----------
  17
  换为*后,是统计t1表中,满足salary>5000这个条件的行的数目。这和COUNT(salary)是差不多的。有一点不同,下面我们把条件去掉:
  gyj@OCM> select count(*) from t1;
  COUNT(*)
  ----------
  22
  这将统计t1表中总共有多少行。*号表示,这个统计,是针对所有列的。而如果将COUNT(*)换为COUNT(salary),如下:
  gyj@OCM> select count(salary) from t1;
  COUNT(SALARY)
  -------------
  18
  这将只统计SALARY列有多少行数据。和其他函数一样,COUNT将忽略空值。
  在COUNT中,也可以使用DISTINCT去掉重复值,只统计非重复行的数目:
  gyj@OCM> select count(distinct salary) from t1;
  COUNT(DISTINCTSALARY)
  ---------------------
  11
  在salary列,的确只有11种值。当然,空值仍然不被计算在内,但可以使用NVL将空值转换为0。
  
  四、分组与组函数
  1、分组 GROUP BY
  分组的语法是:GROUP BY 列名1,列名2,……
  分组的作用是根据某些列的值,将这些列值相同的行分为一组。这就是分组。分组和组函数和在一起,可以完成非常强大的功能。组函数从名字上就表现出来了,“组”(重读)函数吗,针对分组的函数。下面我们看一下t3测试表:
  gyj@OCM> select * from t3;
  ID NAME SALARY
  ---------- ---------- ----------
  1 gyj1 5000
  1 gyj11 5000
  2 gyj2 6000
  2 gyj22 6000
  3 gyj3 7000
  3 gyj33 7000
  4 gyj4 8000
  4 gyj44 8000
  gyj@OCM> select id,sum(salary) from t3 group by id;
  ID SUM(SALARY)
  ---------- -----------
  1 10000
  2 12000
  4 16000
  3 14000
  先对t3表的id列进行分组,分组后两个1合并成一个1,两个2合并成一个2,两个3合并成一个3,两个4合并成一个4,所有重复的值都被合并为一个。在分组的同时,使用SUM(SALARY),计算每个小组中薪水的总和。
  我们可以在分组时使用所有的组函数,对每一个小组内的数据,分别求和、求平均、最大值、最小值,和统计行数:
  gyj@OCM> select id,sum(salary),avg(salary),max(salary),min(salary),count(*) from t3 group by id;
  ID SUM(SALARY) AVG(SALARY) MAX(SALARY) MIN(SALARY) COUNT(*)
  ---------- ----------- ----------- ----------- ----------- ----------
  1 10000 5000 5000 5000 2
  2 12000 6000 6000 6000 2
  4 16000 8000 8000 8000 2
  3 14000 7000 7000 7000 2
  这个命令中,我使用了我们所讲过的每一个组函数。
  在分过组后,非分组列是不能直接显示的,比如:
  gyj@OCM> select id,salary from t3 group by id;
  select id,salary from t3 group by id
  *
  ERROR at line 1:
  ORA-00979: not a GROUP BY expression
  分组后ID被合并成四行,行值分别是1、2、3、4,而SALARY列仍有8行值。这样的话,ORACLE没办法把这两个列组合到一起。因此,就报出了错误。
  通常在分组后,在SELECT 和 FROME之间的列名表中,只能出现分组列。要想出现其他列,必须用组函数把列中的行值处理一下,就像上面的例子,SALARY有8行,必须使用组函数,将8行也处理为4行。
  gyj@OCM> select id,salary from t3 group by id,salary;
  ID SALARY
  ---------- ----------
  1 5000
  2 6000
  3 7000
  4 8000
  2、在Group by中使用函数
  gyj@OCM> select name from t3 group by substr(name,1,4);
  select name from t3 group by substr(name,1,4)
  *
  ERROR at line 1:
  ORA-00979: not a GROUP BY expression
  这个命令报出了错误,但是ORACLE已经指出了,错误不在我们的分组子句中,分组子句是对的,分组中可以使用函数。将NAME的前4个字符截取出来,根据这4个字符进行分组,Oracle可以实现这样的功能。错在SELECT 后的列名表NAME上,分组后只剩4个值,而NAME却有8个值。正确的形式是:
  gyj@OCM> select substr(name,1,4),count(*) from t3 group by substr(name,1,4);
  SUBSTR(N COUNT(*)
  -------- ----------
  gyj4 2
  gyj2 2
  gyj1 2
  gyj3 2
  我同时用COUNT(*)计算一下分组后,每个小组中的行数。
  SELECT后的列名表,除了组函数,其他内容必须和GROUP BY的分组表达式一样!!!
  3、条件
  有两种方法限制分组的行,一是在分组前,使用WHERE,过滤掉不满足条件的行,只对满足条件的行分组。二是,在分组后使用HAVING,只显示满足条件的分组结果。
  先说WHERE。
  (1)WHERE 条件
  我想对薪水大于5000的员工以ID进行分组
  gyj@OCM> select id,count(*) from t3 where salary>5000 group by id;
  ID COUNT(*)
  ---------- ----------
  2 2
  4 2
  3 2
  和普通的分组没什么两样,只是在GROUP BY前加了个条件而已。
  注意,WHERE中条件的判断,优先于分组的执行。先判断条件,对满足条件的行分组。
  (2)HAVING 条件
  HAVING是在分组后,只显示满足条件的行。
  接着前面的例子,比如说,在分组后,只查id大于的信息:
  gyj@OCM> select id,count(*) from t3 where salary>5000 group by id having id>2;
  ID COUNT(*)
  ---------- ----------
  4 2
  3 2
  HAVING后的条件不能挪到WHERE中,因为在执行到WHERE时,ORACLE还没有开始分组,此时执行组函数SUM,将会报错。
  而HAVING的使用,也有限制,HAVING是在分组后执行。分组后,原表中的列除分组列外,都将不能直接使用。
  gyj@OCM> select id,count(*) from t3 group by id having salary>5000;
  select id,count(*) from t3 group by id having salary>5000
  *
  ERROR at line 1:
  ORA-00979: not a GROUP BY expression
  我将上面WHERE后的条件salary>5000,挪到了HAVING之后,报出了错误。在HAVING后,和SEELCT … FROM这间的列一样,只能有分组列,和经过组函数处理过的其他列。
  4、GROUP BY中不能使用别名
  gyj@OCM> select id,count(*) from t3 where salary>5000 group by 1;
  select id,count(*) from t3 where salary>5000 group by 1
  *
  ERROR at line 1:
  ORA-00979: not a GROUP BY expression
  id在第一列,用id分组,在group by中我用1表示用第一列id分组,不能用这种方式和order by不一样!!!
  gyj@OCM> select id bh,count(*) from t3 where salary>5000 group by bh;
  select id bh,count(*) from t3 where salary>5000 group by bh
  *
  ERROR at line 1:
  ORA-00904: "BH": invalid identifier
  我把ID列设为别名为bh,然后用bh分组报错
  gyj@OCM> select id bh,count(*) from t3 where salary>5000 group by id;
  BH COUNT(*)
  ---------- ----------
  2 2
  4 2
  3 2
  我把ID列设为别名为bh,然后用id分组没问题,这个地方要注意!
  
  五、组函数的嵌套
  单行函数和和组函数可以嵌套使用,组函数和组函数也可以嵌套使用。例如:
  gyj@OCM> select sum(salary) from t3 group by id;
  SUM(SALARY)
  -----------
  10000
  12000
  16000
  14000
  我根据id对表分组,并计算出每一组的总薪水。现在我想在此基础上,求出哪一组的总薪水最高:
  gyj@OCM> select max(sum(salary)) from t3 group by id;
  MAX(SUM(SALARY))
  ----------------
  16000
  这就是组函数的嵌套使用。ORACLE中规定,组函数嵌套只能嵌两层。其实多层嵌套并没有实际的用途,因此ORACLE没有提供组函数的多层嵌套。但是,单行函数是可以多层嵌套的。
  
参考技术A try:
select deptno,
sum(case job when 'SALESMAN' then 1 else 0 end) sumjob
from emp
group by deptno
参考技术B 不可以 ,ORACLE SUM()函数的创建算法决定了这样是不行的。。它会把SELECT当成表中的一个字段,然后判断不存在,没办法。但是直接用数字是可行的,比如SUM(2009)或者SUM('2009')本回答被提问者采纳 参考技术C 你试试不就知道了 不过最好这样写

select deptno , sum(sal) from emp where job = 'SALESMAN' group by deptno

你这样试试
select deptno,sum(select sal from emp t1 where job='SALESMAN' and t.job = t1.job) from emp t group by deptno;

Oracle 中的嵌套分析函数

【中文标题】Oracle 中的嵌套分析函数【英文标题】:Nested analytic functions in Oracle 【发布时间】:2013-01-04 03:59:16 【问题描述】:

我们可以在解析函数中使用嵌套解析函数吗?我们可以在表达式中使用另一个解析函数吗?

请给我一个例子。

【问题讨论】:

哥们的表情是什么意思 【参考方案1】:

不,您不能嵌套分析函数。来自manual:

您不能通过指定任何分析函数来嵌套分析函数 在 analytic_clause 的任何部分。但是,您可以指定一个 子查询中的分析函数并计算另一个分析函数 在它上面。

例如:

SQL> select sum(count(*) over ()) over () from dual;
select sum(count(*) over ()) over () from dual
           *
ERROR at line 1:
ORA-30483: window  functions are not allowed here

【讨论】:

以上是关于oracle 分组函数里可以嵌套吗?的主要内容,如果未能解决你的问题,请参考以下文章

oracle 可以用level来分组吗

在oracle里 group by 分组是怎么回事 为啥有时候不加group by说不是单组分组函数?

使用sql的分组函数之后,怎样在被分组的数据

Oracle通用函数,分组函数,子查询

Oracle分组函数之ROLLUP

Oracle——分组函数