SQL 没有数据的 CASE 语句

SQL CASE Statement for no data

我有一个 table 进程引擎 1,2,3,4,5,6,状态为 运行。当其中一个引擎停机时,记录将从 table 中删除。使用 case 语句,我可以显示第一个停机的引擎,但如果有 2 个或更多引擎停机,我该如何显示这些引擎。例如如果两个引擎都已关闭,我如何让此查询显示 PE 2 IS DOWN 和 PE 4 is DOWN。现在它只显示列表中第一个停机的引擎。

    SELECT CASE
WHEN (SELECT COUNT(PE_ID) FROM CWVMINFO WHERE PE_ID = 1) = 0 THEN 'PE 1 IS DOWN'
WHEN (SELECT COUNT(PE_ID) FROM CWVMINFO WHERE PE_ID = 2) = 0 THEN 'PE 2 IS DOWN'
WHEN (SELECT COUNT(PE_ID) FROM CWVMINFO WHERE PE_ID = 3) = 0 THEN 'PE 3 IS DOWN'
WHEN (SELECT COUNT(PE_ID) FROM CWVMINFO WHERE PE_ID = 4) = 0 THEN 'PE 4 IS DOWN'
WHEN (SELECT COUNT(PE_ID) FROM CWVMINFO WHERE PE_ID = 5) = 0 THEN 'PE 5 IS DOWN'
WHEN (SELECT COUNT(PE_ID) FROM CWVMINFO WHERE PE_ID = 6) = 0 THEN 'PE 6 IS DOWN'
ELSE 'ALL PROCESS ENGINES ARE UP AND RUNNING'
END "STATUS"
from dual;

您可以使用多个 CASE 表达式来 return 每个状态:

WITH cte AS (
SELECT CASE WHEN (SELECT COUNT(PE_ID) FROM CWVMINFO WHERE PE_ID = 1) = 0 THEN 'PE 1 IS DOWN' END AS PE_1
      ,CASE WHEN (SELECT COUNT(PE_ID) FROM CWVMINFO WHERE PE_ID = 2) = 0 THEN 'PE 2 IS DOWN' END AS PE_2
      ,CASE WHEN (SELECT COUNT(PE_ID) FROM CWVMINFO WHERE PE_ID = 3) = 0 THEN 'PE 3 IS DOWN' END AS PE_3
      ,CASE WHEN (SELECT COUNT(PE_ID) FROM CWVMINFO WHERE PE_ID = 4) = 0 THEN 'PE 4 IS DOWN' END AS PE_4
      ,CASE WHEN (SELECT COUNT(PE_ID) FROM CWVMINFO WHERE PE_ID = 5) = 0 THEN 'PE 5 IS DOWN' END AS PE_5
      ,CASE WHEN (SELECT COUNT(PE_ID) FROM CWVMINFO WHERE PE_ID = 6) = 0 THEN 'PE 6 IS DOWN' END AS PE_6
       from dual)
SELECT *,CASE WHEN COALESCE(PE_1,PE_2,PE_3,PE_4,PE_5,PE_6) IS NULL THEN 'ALL PROCESS ENGINES ARE UP AND RUNNING' END "STATUS"
FROM cte

我会为这里的每个案例编写一个带有 if 条件的存储过程。

您可以尝试以下方法。这有点笨拙,但我认为它可能会起作用。

WITH p1 AS (
    SELECT LEVEL AS pe_id
      FROM dual
   CONNECT BY LEVEL <= 6
)
SELECT DISTINCT CASE WHEN all_ind = 0 THEN 'ALL PROCESS ENGINES ARE UP AND RUNNING'
  WHEN process_cnt = 0 THEN 'PE ' || pe_id || ' IS DOWN' END AS status
  FROM (
    SELECT pe_id, process_cnt
         , SUM(DECODE(process_cnt, 0, 1, 0)) OVER ( ) AS all_ind
      FROM (
        SELECT p1.pe_id, COUNT(c1.pe_id) AS process_cnt
          FROM p1 LEFT JOIN cwvminfo c1
            ON p1.pe_id = c1.pe_id
         GROUP BY p1.pe_id
    )
)

Please see SQL Fiddle here.

而不是大小写,使用 union all 来表示两种不同的情况,所有的都很好,有些则不是 运行。子查询分解以减少重复代码。

with engines as (select level as engine_number 
    from dual 
    connect by level <= 6)
, down_engines as (select engine_number
    from engines
    where engine_number not in (select pe_id from cwvminfo))
select to_char(engine_number) || ' IS DOWN'
from down_engines 
union all
select 'all engines are running'
from dual
where not exists (select null from down_engines)

我会使用单个查询和条件聚合重写它:

select coalesce(case when sum(case when pe_id = 1 then 1 else 0 end) = 0
                     then 'PE 1 IS DOWN; '
                end) ||
               (case when sum(case when pe_id = 1 then 2 else 0 end) = 0
                     then 'PE 2 IS DOWN; '
                end) ||
               (case when sum(case when pe_id = 1 then 3 else 0 end) = 0
                     then 'PE 3 IS DOWN; '
                end) ||
               (case when sum(case when pe_id = 1 then 4 else 0 end) = 0
                     then 'PE 4 IS DOWN; '
                end) ||
               (case when sum(case when pe_id = 1 then 5 else 0 end) = 0
                     then 'PE 5 IS DOWN; '
                end) ||
               (case when sum(case when pe_id = 1 then 6 else 0 end) = 0
                     then 'PE 6 IS DOWN; '
                end), 'ALL PROCESS ENGINES ARE UP AND RUNNING') as status
from CWVMINFO;

或者,如果您不需要一行,您可以这样做:

select ids.id,
       (case when count(c.pe_id) = 0 then "DOWN' else 'UP' end) as status
from (select 1 as id from dual union all select 2 from dual union all select 3 from dual union all
      select 4 union all select 5 union all select 6 from dual
     ) ids left join
     CWVMINFO c
     on c.pe_id = ids.id
group by ids.id
order by ids.id;

这将使一切都在检查中变得更加明显。

您可以使用 COALESCELISTAGG:

SELECT COALESCE(
         LISTAGG('PE ' || pe_id || ' IS DOWN', ' and ')
           WITHIN GROUP (ORDER BY pe_id),
         'ALL PROCESS ENGINES ARE UP AND RUNNING'
       ) AS status
FROM   (
  SELECT DISTINCT pe_id
  FROM   CWVMINFO
)

其中,对于示例数据:

CREATE TABLE CWVMINFO (pe_id NUMBER);

输出:

STATUS
ALL PROCESS ENGINES ARE UP AND RUNNING

如果你:

INSERT INTO CWVMINFO (pe_id) VALUES (1);

然后输出:

STATUS
PE 1 IS DOWN

那么,如果你:

INSERT INTO CWVMINFO (pe_id) VALUES (3);

然后输出:

STATUS
PE 1 IS DOWN and PE 3 IS DOWN

db<>fiddle here