Using select in the “ELSE” of a CASE statement gives me ORA-00937: not a single-group group function

吃可爱长大的小学妹 提交于 2020-04-14 07:37:31

问题


When I try to have a select statement using listagg in the ELSE portion of my query, I get ORA-00937 error. Any way around this?

select 
CASE 
    when count(*) = 0 then 
        'There are no users connected' 
    else 
        (select 
        listagg(osuser, ', ') within group (order by osuser) 
        from (select distinct osuser from v$session) 
        where osuser != 'SYSTEM' and osuser not like 'VMCONFTEST%')
end 
from v$session
where username is not null 
and osuser not like 'VMCONFTEST%';

Even if I replace the select statement with something simpler, such as select osuser from v$session I get the same error.


回答1:


Taking a slightly different approach but it appears to work. Instead of casing and doing a count, simply check if the aggregate is null (coalesce returns the first non-null value in a series) and if it is substitute your message. This avoids a 2nd level grouping which I don't believe is needed.

Too bad listagg doesn't support distinct within the aggregate as well; we could avoid the inline view.

SELECT coalesce(listagg(A.osuser, ', ') within group (order by A.osuser), 
                'There are no users connected') as userList
FROM (select distinct osuser from v$session) A
WHERE A.osuser!= 'SYSTEM' and A.osuser not like 'VMCONFTEST%'

This does have the overhead in that it attempts to generate a list of users which your case statement may be attempting to short circuit. However if there are no records in V$session the select distinct should be quick.

Though to be honest I'm not sure why we need to do this. Null in the list is generally an adequate response indicating no users. and the UI would handle null meaning no users.

May even be faster if we more the where clause to the inline view..

SELECT coalesce(listagg(A.osuser, ', ') within group (order by A.osuser), 
                'There are no users connected') as userList
FROM (SELECT distinct osuser 
      FROM v$session
      WHERE A.osuser!= 'SYSTEM' 
        and A.osuser not like 'VMCONFTEST%') A



回答2:


Your statement is missing a group by clause, the below for example works:

select distinct(
CASE 
when count(*) = 0 then 
    'There are no users connected' 
else 
    (select 
    listagg(osuser, ', ') within group (order by osuser) 
    from (select distinct osuser from v$session) 
    where osuser != 'SYSTEM' and osuser not like 'VMCONFTEST%')
end)
from v$session
where username is not null 
and osuser not like 'VMCONFTEST%'
GROUP BY osuser;



回答3:


select 
CASE 
   when cnt = 0 then 
    'There are no users connected' 
   else 
    (select 
     listagg(osuser, ', ') within group (order by osuser) 
     from (select distinct osuser from v$session) t
    where osuser != 'SYSTEM' and t.osuser not like 'VMCONFTEST%')
end result
from
 (select count(*) as cnt
 from v$session
 where username is not null 
and osuser not like 'VMCONFTEST%');



回答4:


with conn_users as 
     (select count(*) conn_users
      from v$session
      where osuser != 'SYSTEM' 
        and osuser not like 'VMCONFTEST%'),
  aggr_users as       
     (select listagg(osuser, ', ') within group (order by osuser) 
        from (select distinct osuser from v$session) 
        where osuser != 'SYSTEM' and osuser not like 'VMCONFTEST%')
select 
CASE 
    when (select * from conn_users)  = 0 then 
        'There are no users connected' 
    else 
      (select * from aggr_users)
end 
from dual;

The problem was the count that cannot stand there

In plus when I need to perform complex subqueries I love to use with clause Probably this query can be improved centralizing the conditions (that are duplicated)



来源:https://stackoverflow.com/questions/35180792/using-select-in-the-else-of-a-case-statement-gives-me-ora-00937-not-a-single

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!