【问题标题】:Using select in the "ELSE" of a CASE statement gives me ORA-00937: not a single-group group function在 CASE 语句的“ELSE”中使用 select 给我 ORA-00937: not a single-group group function
【发布时间】:2016-02-03 15:15:03
【问题描述】:

当我尝试在查询的 ELSE 部分中使用 listagg 选择语句时,我收到 ORA-00937 错误。有什么办法吗?

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%';

即使我将 select 语句替换为更简单的语句,例如 select osuser from v$session,我也会遇到同样的错误。

【问题讨论】:

  • 你如何通过执行SELECT osuser FROM v$Session得到ORA-00937

标签: oracle case


【解决方案1】:

采用稍微不同的方法,但似乎可行。 无需封装并进行计数,只需检查聚合是否为空(coalesce 返回系列中的第一个非空值)以及它是否替代您的消息。这避免了我认为不需要的第二级分组。

太糟糕了 listagg 也不支持在聚合中区分;我们可以避免内联视图。

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%'

这确实有开销,因为它会尝试生成您的案例语句可能试图短路的用户列表。但是,如果 V$session 中没有记录,则 select distinct 应该很快。

说实话,我不确定我们为什么需要这样做。列表中的空值通常是表示没有用户的适当响应。并且 UI 将处理 null 表示没有用户。

如果我们将 where 子句添加到内联视图中,可能会更快..

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】:

    您的语句缺少 group by 子句,以下示例有效:

    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;
    

    【讨论】:

    • 我认为这会导致返回超过 1 条记录。最初的问题不是只有一条记录吗?
    • 确实,很明显 - 添加了一个独特的子句。手头的任务会有更好的方法,但它确实修复了 ORA-00937
    【解决方案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;
      

      问题是计数不能站在那里

      此外,当我需要执行复杂的子查询时,我喜欢使用 with 子句 可能这个查询可以改进集中条件(重复)

      【讨论】:

        猜你喜欢
        • 2021-09-08
        • 2022-09-23
        • 1970-01-01
        • 2015-08-18
        • 1970-01-01
        • 2021-04-03
        • 2013-11-19
        • 1970-01-01
        • 2015-08-20
        相关资源
        最近更新 更多