Oracle SQL,在带联合的查询中总是显示三行

Oracle SQL, always show three lines in query with unions

我return下面的数据来自数据库。我根据状态,计算特定状态的物品数量和最旧物品的年龄。

select distinct 1, dm1.technology, dm1.name_event, count(dm1.id) as "Number of items", max(TO_CHAR(TO_DATE('20000101','yyyymmdd')+(SYSDATE - dm1.time_event),'hh24:mi:ss')) as "Time in system" from dm_procmon dm1 join dm_procmon dm2 on dm1.id = dm2.id
where  dm1.name_event = 'state1' and (select count(*) from dm_procmon dm2 where dm1.id= dm2.id and dm2.name_event = 'state2') = 0
group by dm1.technology, dm1.name_event
UNION
select distinct 2, dm1.technology, dm1.name_event, count(dm1.id) as "Number of items", max(TO_CHAR(TO_DATE('20000101','yyyymmdd')+(SYSDATE - dm1.time_event),'hh24:mi:ss')) as "Time in system" from dm_procmon dm1 join dm_procmon dm2 on dm1.id = dm2.id
where dm1.name_event = 'state2' and (select count(*) from dm_procmon dm2 where dm1.id= dm2.id and dm2.name_event = 'state3') = 0
group by dm1.technology, dm1.name_event
UNION
select distinct 3, dm1.technology, dm1.name_event, count(dm1.id) as "Number of items", max(TO_CHAR(TO_DATE('20000101','yyyymmdd')+(SYSDATE - dm1.time_event),'hh24:mi:ss')) as "Time in system" from dm_procmon dm1
where dm1.name_event = 'state3' and (select count(*) from dm_procmon dm2 where dm1.id= dm2.id and dm2.name_event = 'end state') = 0
group by dm1.technology , dm1.name_event

问题是,当特定状态下有 0 个项目时,该状态的行将被忽略。这意味着如果例如状态 3 0 项目有,则该行根本不显示...

当前输出,错误

     1 TECHNOLOGY           NAME_EVENT        Number of items Time in system
---------- -------------------- ----------------- --------------- --------------
     1 Repository           state1                          4 00:19:51
     2 Repository           state2                          1 00:28:21

我想要实现的输出

     1 TECHNOLOGY           NAME_EVENT        Number of items Time in system
 ---------- -------------------- ----------------- --------------- --------------
     1 Repository           state1                          4 00:19:51
     2 Repository           state2                          1 00:28:21
     3 Repository           state3                          0 00:00:00

您可以使用 UNIONNOT EXISTS.

显式添加行

例如,让我们看一个测试用例:

SQL> SELECT deptno dept, count(*) cnt FROM emp WHERE deptno = 20
  2  GROUP BY deptno
  3  UNION
  4  SELECT deptno dept, count(*) cnt FROM emp WHERE deptno = 100
  5  GROUP BY deptno
  6  /

      DEPT        CNT
---------- ----------
        20          5

SQL>

即使没有 deptno = 100 的部门,我也希望显示一行。

SQL> SELECT to_char(deptno) dept, count(*) cnt FROM emp WHERE deptno = 20
  2  group by to_char(deptno)
  3  UNION
  4  SELECT 'No departments found' dept, 0 cnt
  5  FROM dual
  6  WHERE NOT EXISTS
  7    (SELECT 1 FROM emp WHERE deptno = 100
  8    )
  9  /

DEPT                                            CNT
---------------------------------------- ----------
20                                                5
No departments found                              0

SQL>

在上面的示例中,没有 department = 100 的行,但我正在显示它。

检查此查询(需要 Oracle 11g):

SQLFiddle

with data1 as (
  select id, technology tg, 
      max(decode(name_event, 'state1', 1, 0)) st1, 
      max(decode(name_event, 'state2', 1, 0)) st2, 
      max(decode(name_event, 'state3', 1, 0)) st3,
      sum(decode(name_event, 'end state', 1, 0)) st4,
      max(to_char(date '2000-01-01'+(sysdate - time_event), 'hh24:mi:ss')) tis
    from dm_procmon group by id, technology ), 
data2 as ( 
  select tg, count(case when st1 = 1 and st2 = 0 then id end) st1,
      count(case when st2 = 1 and st3 = 0 then id end) st2,
      count(case when st3 = 1 and st4 = 0 then id end) st3,
      max(case when st1 = 1 and st2 = 0 then tis else '00:00:00' end) tis1,
      max(case when st2 = 1 and st3 = 0 then tis else '00:00:00' end) tis2,
      max(case when st3 = 1 and st4 = 0 then tis else '00:00:00' end)tis3
    from data1 group by tg
  )
select tg technology, st state, max(noi) items, max(tis) max_time 
  from (
    select *
      from data2
      unpivot (noi for st in (st1 as 'state1', st2 as 'state2', st3 as 'state3'))
      unpivot (tis for ti in (tis1 as 'state1', tis2 as 'state2', tis3 as 'state3')) 
    ) 
    where st=ti group by tg, st order by tg, st

我能够稍微简化这个查询,最后一部分应该是:

select tg technology, event, items, max_time 
  from data2
  unpivot ((items, max_time) for (event, t) in (
    (st1, tis1) as ('state1', null), 
    (st2, tis2) as ('state2', null),
    (st3, tis3) as ('state3', null) ))
  order by technology, event