Код Matlab двух методов, опубликованных в высоко оцененных журналах (IEEE Transactions on Image Processing), доступен здесь: https://ivulab.asu.edu/software
проверить алгоритмы CPBDM и JNBM. Если вы проверите код, его не очень сложно портировать, и, кстати, он основан на методе Марциалиано как основной функции.
-- 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
Вы можете использовать условную агрегацию через выражение 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
, но он делает то же самое под капотом, и, вероятно, излишним для этого простого сценария.
Попробуйте это:
select logdate, ok, notok from your_table
pivot (count(status) for status in ('ok' as ok, 'notok' as notok));