在SQL的count(*)函数中包含0

时间:2016-12-01 05:39:07

标签: sql oracle count decode

我正在使用此命令获取状态:

SELECT  DECODE(processed,1,'Complete', 'Incomplete') Last_Day_Report_Status,       
        COUNT(*) 
FROM Table_demo 
WHERE run_datetime >= trunc(sysdate)-1
  AND run_datetime < trunc(sysdate)
GROUP BY DECODE(processed,1,'Complete','Incomplete');

它应该输出如下:

完成:120

不完整:0

但它只给予: 完成:120

2 个答案:

答案 0 :(得分:5)

WITH parameter as (
     SELECT 'Complete' as status FROM DUAL
     UNION ALL
     SELECT 'Incomplete' as status FROM DUAL
)
SELECT  parameter.status as  Last_Day_Report_Status,       
        COUNT(status) 
FROM parameter 
LEFT JOIN Table_demo 
  ON parameter.status = DECODE(status ,1,'Complete', 'Incomplete')
WHERE run_datetime >= trunc(sysdate)-1
  AND run_datetime < trunc(sysdate)
GROUP BY parameter.status;

答案 1 :(得分:0)

此解决方案的优点应该是速度。它将Table_demo汇总为一行,这样就不需要为每个使用过的Table_demo行计算连接。

SELECT
  Last_Day_Report_Status, 
  DECODE(Last_Day_Report_Status, 'Complete',  NVL(Completed,0), NVL(Total-Completed,0)) counts
FROM 
   ( SELECT 'Complete' Last_Day_Report_Status FROM DUAL
     UNION ALL
     SELECT 'Incomplete' Last_Day_Report_Status FROM DUAL
   )
     OUTER APPLY
  ( SELECT  COUNT(DECODE(processed,1,'Complete')) Completed, COUNT(1) Total
    FROM Table_demo 
    WHERE run_datetime >= TRUNC(SYSDATE)-1
      AND run_datetime < TRUNC(SYSDATE)
  );

这个问题的一大问题是优化器拒绝首先处理子查询,或者即使在暗示死亡时也作为哈希联接处理,导致总和运行两次,欢迎评论。我所拥有的查询的最明确的优化(尽管1 = 1的丑陋假连接),遗憾的是仍然从联合到求和的嵌套循环,是:

SELECT /*+ ordered  */
  Last_Day_Report_Status, 
  DECODE(Last_Day_Report_Status, 'Complete', NVL(Completed,0), NVL(Total-Completed,0)) counts
FROM 
  ( SELECT COUNT(DECODE(processed,1,'Complete')) Completed, COUNT(1) Total
    FROM Table_demo 
    WHERE run_datetime >= TRUNC(SYSDATE)-1
      AND run_datetime < TRUNC(SYSDATE)
  )
   RIGHT OUTER JOIN
 ( SELECT 'Complete' Last_Day_Report_Status FROM DUAL
   UNION ALL
   SELECT 'Incomplete' Last_Day_Report_Status FROM DUAL
 ) ON 1=1;

优化器觉得无法使用ORDERED提示请求按查询顺序执行子查询。

给定优化路径并假设Table_demo可能很大,求和可以实现(预先封装)。具体化过程具有启动成本,因此在每秒执行100次或1000次的循环中可能是昂贵的。尽管计数实体化查询被访问两次(对于联合的每一行一次),但它仍然需要未记录的/*+ MATERIALIZE */提示来阻止它INLINE编辑,ROWNUM在{{{ 1}}强制这不会起作用,因为它知道只有一行。这提供了一个很好的优化:

SELECT

我使用的优化版本是Oracle 12.1.0.1 SE。我在没有检查执行跟踪的情况下采用了面值的解释计划。