首页 > 解决方案 > 选择两个计数相同的列不同的地方

问题描述

我有一张桌子

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;

标签: sqloracleaggregate-functions

解决方案


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

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,但它在引擎盖下做同样的事情,并且对于这个简单的场景来说可能是矫枉过正。


推荐阅读