选择两个具有相同计数的列,不同之处在

时间:2019-03-18 12:29:16

标签: sql oracle aggregate-functions

我有一张桌子

Logdate,Status

    20190101 ok
    20190101 notok
    20190101 ok
    20190102 ok
    20190102 notok

我想获得如下查询结果:

date     ok  notok
20190101 2   1
20190102 1   1

我不知道如何用2个不同的位置对同一列进行汇总查询 请任何帮助? 谢谢!

编辑--- mi查询

SELECT LOGDATE AS EXECUTION_DATE, COUNT(1) AS TOTAL_OK FROM CMR_IOALOG WHERE UPPER(STATUS) LIKE upper('% OK %') group by logdate ORDER BY LOGDATE DESC;
SELECT LOGDATE AS EXECUTION_DATE COUNT(1) AS TOTAL_NOTOK FROM CMR_IOALOG WHERE UPPER(STATUS) LIKE upper('%NOTOK%') group by logdate ORDER BY LOGDATE DESC;

3 个答案:

答案 0 :(得分:2)

您可以通过count()调用内的case表达式使用条件聚合:

select logdate,
  count(case when status = 'ok' then status end) as ok,
  count(case when status = 'notok' then status end) as notok
from your_table
group by logdate;

count()函数将忽略空值,因此case表达式会为您要计数的状态给出一个非空值,对于其他任何情况默认为​​空值。

将示例数据作为CTE进行演示:

-- CTE for sample data
with your_table (logdate, status) as (
            select 20190101, 'ok' from dual
  union all select 20190101, 'notok' from dual
  union all select 20190101, 'ok' from dual
  union all select 20190102, 'ok' from dual
  union all select 20190102, 'notok' from dual
)
-- actual query
select logdate,
  count(case when status = 'ok' then status end) as ok,
  count(case when status = 'notok' then status end) as notok
from your_table
group by logdate;

   LOGDATE         OK      NOTOK
---------- ---------- ----------
  20190102          1          1
  20190101          2          1

希望您的logdate实际上是日期而不是数字;我刚刚使用了一个数字来匹配您显示的值。如果它是一个日期并且不是午夜时间,那么您可以trunc(logdate)来计算整天的值:

with your_table (logdate, status) as (
            select to_date('20190101 00:01', 'YYYYMMDD HH24:MI'), 'ok' from dual
  union all select to_date('20190101 00:02', 'YYYYMMDD HH24:MI'), 'notok' from dual
  union all select to_date('20190101 00:03', 'YYYYMMDD HH24:MI'), 'ok' from dual
  union all select to_date('20190102 00:01', 'YYYYMMDD HH24:MI'), 'ok' from dual
  union all select to_date('20190102 00:02', 'YYYYMMDD HH24:MI'), 'notok' from dual
)
select trunc(logdate) as logdate,
  count(case when status = 'ok' then status end) as ok,
  count(case when status = 'notok' then status end) as notok
from your_table
group by trunc(logdate);

LOGDATE            OK      NOTOK
---------- ---------- ----------
2019-01-02          1          1
2019-01-01          2          1

您可以改用sum(),并且使case表达式的计算结果为零或一,但是效果是一样的-当总体目的是计算事物时,我更喜欢使用count()

您也可以使用显式的pivot,但实际上它的作用是相同的,在这种简单情况下可能会显得过大。

答案 1 :(得分:1)

-- Oracle 11+
with s (Logdate,Status) as (
select 20190101, 'ok'    from dual union all
select 20190101, 'notok' from dual union all
select 20190101, 'ok'    from dual union all
select 20190102, 'ok'    from dual union all
select 20190102, 'notok' from dual)
select *
from s
pivot (count(*) for status in ('ok' as ok, 'notok' as notok))
order by Logdate;

   LOGDATE         OK      NOTOK
---------- ---------- ----------
  20190101          2          1
  20190102          1          1

答案 2 :(得分:0)

尝试一下:

select logdate, ok, notok from your_table 
    pivot (count(status) for status in ('ok' as ok, 'notok' as notok));