Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在sql中使用case返回零而不是未选择行_Sql_Oracle_Oracle11g - Fatal编程技术网

如何在sql中使用case返回零而不是未选择行

如何在sql中使用case返回零而不是未选择行,sql,oracle,oracle11g,Sql,Oracle,Oracle11g,如果我查询一个不存在的输出,那么我将不会得到任何返回。我正在寻找该场景中返回的默认值(0) select sum(case when a2.status='SUCCESS' THEN A2.a else 0 end) as success, sum(case when a2.status='FAILED' THEN A2.a else 0 end) as failed, sum(case when a2.status='ERROR' THEN A2.a else 0 end) as error

如果我查询一个不存在的输出,那么我将不会得到任何返回。我正在寻找该场景中返回的默认值(0)

select sum(case when a2.status='SUCCESS' THEN A2.a else 0 end) as success,
sum(case when a2.status='FAILED' THEN A2.a else 0 end) as failed,
sum(case when a2.status='ERROR' THEN A2.a else 0 end) as error
from
(select a.stauts,count(1) a 
from table1 a,table2 b
where a.id=b.id
a.date=sysdate
group by a.status)a2; 

注意:sysdate没有记录。我要求状态的默认值“0”应为返回值

您可能会生成缺少的值:

WITH cte AS (
     select a.status,count(1) a 
     from table1 a                  --JOIN syntax
     join table2 b
       on a.id=b.id
     WHERE a.date=sysdate           -- are you sure you want precision with time?
     group by a.status
), placeholder AS (
     SELECT *
     FROM cte
     UNION ALL
     SELECT *
     FROM (SELECT 'SUCCESS' AS status, 0 AS a FROM dual UNION ALL
           SELECT 'ERROR',   0 FROM dual UNION ALL
           SELECT 'FAILED',  0 FROM dual)  p
     WHERE NOT EXISTS (SELECT * FROM cte WHERE cte.status = p.status)
)
SELECT 
  sum(case when status='SUCCESS' THEN a else 0 end) as success,
  sum(case when status='FAILED' THEN a else 0 end) as failed,
  sum(case when status='ERROR' THEN a else 0 end) as error
FROM placeholder;

我想到的唯一建议是在子查询中使用左连接,并将整个
WHERE
逻辑移动到
ON
子句:

SELECT
    SUM(CASE WHEN a2.status = 'SUCCESS' THEN A2.a ELSE 0 END) AS success,
    SUM(CASE WHEN a2.status = 'FAILED'  THEN A2.a ELSE 0 END) AS failed,
    SUM(CASE WHEN a2.status = 'ERROR'   THEN A2.a ELSE 0 END) AS error
FROM
(
    SELECT a.status, COUNT(1) a 
    FROM table1 a
    LEFT JOIN table2 b
        ON a.id = b.id AND
           a.date = SYSDATE
    GROUP BY a.status
) a2;

您当前的查询使用的是过时的联接语法,这使得很难看到实际发生的情况。特别是,它使您很难看到您是否会在加入过程中丢弃希望保留的信息。

此查询应始终返回一行,即使没有匹配的信息:

select sum(case when a.status = 'SUCCESS' then 1 else 0 end) as success,
       sum(case when a.status = 'FAILED' then 1 else 0 end) as failed,
       sum(case when a.status = 'ERROR' then 1 else 0 end) as error
from table1 a join
        table2 b
        on a.id = b.id
where a.date = trunc(sysdate);
注意,我更改了
where
逻辑
sysdate
(尽管名称不同)有一个时间组件。如果
date
有时间成分,您可能需要:

where a.date >= trunc(sysdate) and a.date < trunc(sysdate + 1)
如果使用
COUNT()
,则不需要
NVL()
COALESCE()
来处理
NULL
s,这与
SUM()
的情况不同<当参数为
NULL
或没有匹配行时,code>COUNT()将始终返回值为0的行。
groupby
也不是必需的

SELECT COUNT(CASE WHEN a.status = 'SUCCESS' THEN 1 END) AS success,
       COUNT(CASE WHEN a.status = 'FAILED'  THEN 1 END) AS failed,
       COUNT(CASE WHEN a.status = 'ERROR'   THEN 1 END) AS error
FROM table1 a
JOIN table2 b ON a.id = b.id
WHERE a.date = TRUNC(SYSDATE);
如果您只是想弄清楚,请测试这些查询并注意结果

select SUM(1)    FROM DUAL WHERE 1=0; --NULL
select SUM(NULL) FROM DUAL WHERE 1=0; --NULL
select SUM(NULL) FROM DUAL WHERE 1=1; --NULL
select COUNT(1)  FROM DUAL WHERE 1=0;  -- 0
select COUNT(NULL) FROM DUAL WHERE 1=0; -- 0 
select COUNT(NULL) FROM DUAL WHERE 1=1; -- 0

无分组依据的聚合始终返回一行,因此现有查询将返回空值

要将空值更改为零,只需应用合并:

select
   coalesce(sum(case when a2.status='SUCCESS' THEN A2.a end), 0) as success,
   coalesce(sum(case when a2.status='FAILED'  THEN A2.a end), 0) as failed,
   coalesce(sum(case when a2.status='ERROR'   THEN A2.a end), 0) as error
from
 (
   select a.status,count(1) a 
   from table1 a join table2 b
     on a.id=b.id
   where a.date=sysdate
   group by a.status
 ) a2;

如果我想确保即使对于找不到任何要返回的行的查询,也始终有一个结果,我会在双表上执行左联接(对于oracle):


这样,不管发生什么事,你都会再次吵架

不应该是count(case-when)而不是sum()?您还应该在sum上添加NVL或COALESCE,以处理查询返回no的情况rows@AlexZen:具有聚合且没有分组依据的查询将始终只返回一行。该行将包含整个结果集的统计信息,即使它是空集。@Andomar这是真的,但如果结果集为空,它将返回一行,其中的值为null。因此,您将NVL或COALESCE放在一起,以实现OP要求的(默认值“0”)选择NVL(sum(当a.status='SUCCESS'然后1 else 0 end)作为成功,
select
   coalesce(sum(case when a2.status='SUCCESS' THEN A2.a end), 0) as success,
   coalesce(sum(case when a2.status='FAILED'  THEN A2.a end), 0) as failed,
   coalesce(sum(case when a2.status='ERROR'   THEN A2.a end), 0) as error
from
 (
   select a.status,count(1) a 
   from table1 a join table2 b
     on a.id=b.id
   where a.date=sysdate
   group by a.status
 ) a2;
select q.*  FROM DUAL d LEFT JOIN ( your_query )q on 1=1