Вы можете сделать объединение с таблицей calendar (таблица, содержащая 24 отчетных месяца) более эффективным, если на первом шаге рассчитывается интервал действия, т. Е. Последний день (включительно), в которыйстатус действителен - status_date_to
.
Предлагаемый расчет действителен, если status_date
обрезано, т. е. без времени.
Используйте status_date - interval '1' second
вместо status_date - 1
, еслиесть компонент времени .
Чем вы объединяете только те записи в EPML_HISTORY
, которые соответствуют с reporing_month, то есть c.reporting_month between h.status_date and h.status_date_to
WITH calendar AS (
SELECT trunc(add_months(sysdate, 1-level), 'MM') reporting_month
FROM dual
CONNECT BY level <= 24
), hist as (
SELECT id,
status_date,
nvl(lead(status_date-1) over (partition by id order by status_date),add_months(trunc(sysdate, 'MM'),1)) as status_date_to,
status
from empl_hist)
select REPORTING_MONTH, ID, STATUS
from calendar c
join hist h on c.reporting_month between h.status_date and h.status_date_to
order by id, reporting_month;
REPORTING_MONTH ID STATUS
------------------- ---------- ----------
01.05.2018 00:00:00 1 active
01.06.2018 00:00:00 1 active
01.07.2018 00:00:00 1 active
01.08.2018 00:00:00 1 active
01.09.2018 00:00:00 1 deactive
01.10.2018 00:00:00 1 deactive
01.11.2018 00:00:00 1 deactive
01.12.2018 00:00:00 1 deactive
01.01.2019 00:00:00 1 active
01.08.2018 00:00:00 2 active
01.09.2018 00:00:00 2 active
01.10.2018 00:00:00 2 active
01.11.2018 00:00:00 2 deactive
01.12.2018 00:00:00 2 deactive
01.01.2019 00:00:00 2 deactive
01.01.2019 00:00:00 4 active
Обратите также внимание, что вы можете вернуться к своему логику назначения отчетного месяца с status_date <= (trunc(sysdate, 'month')
.В приведенных ниже примерах данные id=3
игнорируются, поскольку они были активированы 5-го числа текущего месяца, но сообщается id=4
, поскольку они были активны 1-го числа текущего месяца.
ОбразецДанные
drop table empl_hist;
create table empl_hist(
id number,
status_date date,
status varchar2(10));
insert into empl_hist values(1,DATE'2018-05-01','active');
insert into empl_hist values(1,DATE'2018-08-05','deactive');
insert into empl_hist values(1,DATE'2018-12-05','active');
insert into empl_hist values(2,DATE'2018-07-05','active');
insert into empl_hist values(2,DATE'2018-10-05','deactive');
insert into empl_hist values(3,DATE'2019-01-05','active');
insert into empl_hist values(4,DATE'2019-01-01','active');