不是使用select case语句的单组组函数

时间:2015-09-07 13:48:41

标签: sql oracle group-by case-when

我正在编写下面的查询,它将两个选择查询分开并计算百分比。但我收到错误not a single-group group function

select CASE WHEN COUNT(*) = 0 THEN 0 ELSE round((r.cnt / o.cnt)*100,3) END from 
    (Select count(*) as cnt from O2_CDR_HEADER WHERE STATUS NOT IN(0,1) and DATE_CREATED > (SYSDATE - 1)) r cross join
    (Select count(*) as cnt from O2_CDR_HEADER WHERE DATE_CREATED > (SYSDATE - 1)) o;

6 个答案:

答案 0 :(得分:2)

您正在同一SELECT查询中引用聚合函数(COUNT(*))和单个列表达式(r.cnto.cnt)。除非为相关的各列添加了GROUP BY子句,否则这不是有效的SQL。

提供有效的替代方案会更容易,您可以澄清您希望返回的查询(给定样本架构和数据集)。我猜你可以简单地用COUNT(*)替换o.cnt来避免除以0问题。如果预计会出现其他一些逻辑,那么您需要澄清它是什么。

答案 1 :(得分:2)

您不需要使用联接。如果我是你,我会这样做:

select case when count(*) = 0 then 0
            else round(100 * count(case when status not in (0, 1) then 1 end) / count(*), 3)
       end non_0_or_1_status_percentage
from   o2_cdr_header
where  date_created > sysdate - 1;

这是一个简单的演示:

with t as (select 1 status from dual union all
           select 2 status from dual union all
           select 3 status from dual union all
           select 2 status from dual union all
           select 4 status from dual union all
           select 5 status from dual union all
           select 6 status from dual union all
           select 7 status from dual union all
           select 1 status from dual union all
           select 0 status from dual union all
           select 1 status from dual)
select case when count(*) = 0 then 0
            else round(100 * count(case when status not in (0, 1) then 1 end) / count(*), 3)
       end col1
from   t
where 1=0;

      COL1
----------
         0

如果您不确定在case语句中对count进行过滤会返回与在where子句中过滤时相同的情况,那么这是一个证明它的演示:

with t as (select 1 status from dual union all
           select 2 status from dual union all
           select 3 status from dual union all
           select 2 status from dual union all
           select 4 status from dual union all
           select 5 status from dual union all
           select 6 status from dual union all
           select 7 status from dual union all
           select 1 status from dual union all
           select 0 status from dual union all
           select 1 status from dual)
select 'using case statement' how_count_filtered,
       count(case when status not in (0, 1) then 1 end) cnt
from   t
union all
select 'using where clause' how_count_filtered,
       count(*) cnt
from   t
where  status not in (0, 1);

HOW_COUNT_FILTERED          CNT
-------------------- ----------
using case statement          7
using where clause            7

答案 2 :(得分:1)

看起来您希望获得的状态百分比不是0,1,如果没有结果,则为0。

也许这就是你想要的第一行?

SELECT CASE WHEN (R.CNT = 0 AND O.CNT = 0) THEN 0 ELSE ROUND((R.CNT *100.0 / O.CNT),3) END 

答案 3 :(得分:1)

您不需要交叉加入。选择计数并稍后进行分组。

select case when ocnt > 0 then round((rcnt / ocnt)*100,3)
       else 0 end
from
(
select 
CASE WHEN STATUS NOT IN(0,1) and DATE_CREATED > (SYSDATE - 1)
 THEN COUNT(*) END as rcnt,
CASE WHEN DATE_CREATED > (SYSDATE - 1)
 THEN COUNT(*) END as ocnt 
from O2_CDR_HEADER
group by status, date_created
) t

答案 4 :(得分:1)

Boneist的答案很好,但我会把它写成:

select coalesce(round(100 * avg(case when status not in (0, 1) then 1.0 else 0
                                end), 3), 0) as non_0_or_1_status_percentage
from   o2_cdr_header
where  date_created > sysdate - 1;

答案 5 :(得分:0)

以下是适合我的答案

Environment.SetEnvironmentVariable(String EnvironmentVariableName, String EnvironmentVariableValue, EnvironmentVariableTarget.Machine)