如何在CASE语句中使用LISTAGG函数?ORA-00979错误解决
解决ORA-00979错误:CASE语句中正确使用LISTAGG函数
错误原因
ORA-00979的核心问题是:SELECT子句中的EMP.JOB既没有包含在GROUP BY子句中,也没有被聚合函数(如MAX、MIN)包裹。Oracle的GROUP BY规则要求,查询中所有非聚合列必须出现在GROUP BY列表里。
结合你的测试数据,COMM IS NOT NULL的员工均为SALESMAN,原查询的逻辑矛盾在于:按EMPNO分组时每个组仅对应一名员工,此时使用LISTAGG(用于聚合多行数据)并无实际意义,反而因未处理EMP.JOB触发语法错误。
以下是两种符合需求的修正方案:
方案1:保留按员工(EMPNO)分组的逻辑
若你需要对每个COMM不为空的员工,仅当职位为CLERK/SALESMAN时输出其薪资(单条记录场景下LISTAGG等价于直接取薪资,但按你的写法调整),可通过两种方式修复:
方式A:将EMP.JOB加入GROUP BY
select case when EMP.JOB in ('CLERK','SALESMAN') then listagg(DISTINCT EMP.SAL, ';') within group (order by EMP.EMPNO) end as sal from EMP where EMP.COMM is not null group by EMP.EMPNO, EMP.JOB
方式B:用聚合函数包裹EMP.JOB
因每个EMPNO对应唯一职位,使用MAX/MIN不影响结果:
select case when MAX(EMP.JOB) in ('CLERK','SALESMAN') then listagg(DISTINCT EMP.SAL, ';') within group (order by EMP.EMPNO) end as sal from EMP where EMP.COMM is not null group by EMP.EMPNO
这两种写法都会返回每个符合条件员工的薪资,不符合职位要求的记录返回NULL。
方案2:按职位分组,拼接同职位薪资
若你的真实需求是将COMM不为空的员工中,职位为CLERK/SALESMAN的薪资按职位分组拼接,需调整GROUP BY为JOB:
select EMP.JOB, case when EMP.JOB in ('CLERK','SALESMAN') then listagg(DISTINCT EMP.SAL, ';') within group (order by EMP.EMPNO) end as sal from EMP where EMP.COMM is not null group by EMP.JOB
根据你的测试数据,该查询会返回SALESMAN对应的去重薪资拼接结果:1600;1250;1500。
内容的提问来源于stack exchange,提问作者Raaj
相关产品推荐
相关产品推荐

