Обзор
Суть решения является 2-ступенчатый подход.
Сначала учтите первоначальные записи, упорядоченные в соответствии с Date
, и последовательные записи с тем же значением Field
, сгруппированным, отмечая максимальные и минимальные даты каждой из указанных групп. В записях сгенерированных результирующих данных указаны максимальные интервалы дат, в пределах которых значение поля не изменяется (этот выбор инкапсулирован в виде vtest_lag
в примере ниже).
Далее присоединитесь к этому новому набору результатов с запаздыванием 1 на одной из его даты столбца. Таким образом, примыкающие интервалы спарены в окончательном результирующем, что позволяет обновлять Field
значения по желанию.
Предостережения
- решение не принимает на себя никаких дубликатов даты в исходных данных
- Решение не связана с эффективностью
SQL-раствор
Этот автономный пример агностиком к SQL диалектов помимо rownum
псевдостолбец оракула подачи порядковый номер записи в результирующем. Есть эквивалентные функции в других вкусах sql.
Часть 1/2: Настройка
create table test_lag (
t_date date
, field varchar2(10)
, desirednew varchar2(10)
, computednew varchar2(10)
);
insert into test_lag values (to_date ('01/09/1994', 'DD/MM/YYYY'), 'D', 'C' , null);
insert into test_lag values (to_date ('01/08/1994', 'DD/MM/YYYY'), 'D', 'C' , null);
insert into test_lag values (to_date ('01/07/1994', 'DD/MM/YYYY'), 'D', 'C' , null);
insert into test_lag values (to_date ('01/06/1994', 'DD/MM/YYYY'), 'C', 'B' , null);
insert into test_lag values (to_date ('01/05/1994', 'DD/MM/YYYY'), 'B', 'A' , null);
insert into test_lag values (to_date ('01/04/1994', 'DD/MM/YYYY'), 'B', 'A' , null);
insert into test_lag values (to_date ('01/03/1994', 'DD/MM/YYYY'), 'B', 'A' , null);
insert into test_lag values (to_date ('01/02/1994', 'DD/MM/YYYY'), 'A', null , null);
insert into test_lag values (to_date ('01/01/1994', 'DD/MM/YYYY'), 'A', null , null);
Часть 2/2: Обновление
Посмотреть vtest_lag
инкапсулирует запрос предоставить данные для обновления заявление.
create or replace view vtest_lag as
select emb.*
, rownum seq
from (
select *
from (
select sysdate t_date1
, null field1
, t_date t_date2
, field field2
from test_lag
where t_date = (select max(t_date) from test_lag)
union all
select t_date t_date1
, field field1
, to_date('01/01/1900', 'DD/MM/YYYY')
t_date2
, null field2
from test_lag
where t_date = (select min(t_date) from test_lag)
union all
select po1.t_date t_date1
, po1.field field1
, po2.t_date t_date2
, po2.field field2
from (
select po1_base.*
, rownum seq
from (
select *
from test_lag
order by t_date desc
) po1_base
) po1
join (
select po2_base.*
, rownum seq
from (
select *
from test_lag
order by t_date desc
) po2_base
) po2
on po2.seq = po1.seq + 1
where po1.field <> po2.field
)
order by t_date1 desc
) emb
;
update test_lag trg
set trg.computednew = (select v2.field2 from vtest_lag v1 join vtest_lag v2 on v2.seq = v1.seq+1 where trg.t_date <= v1.t_date2 and trg.t_date >= v2.t_date1)
;
спасибо. Мои данные более сложны и включают повторяющиеся даты с другим полем последовательности. Я просмотрю ваш ответ, хотя и очень ценю это. Поскольку он не видит, как существует компактное решение, я могу импортировать данные в R, где я могу легко манипулировать с помощью: – Patrick
.i <- list ("vector") для (i in 1: nrow (dat)) { для (j in 1: nrow (dat)) { if ((dat [i, 2] == dat [ max (i, j), 2]) == FALSE) { out.i [[i]] <- data.frame (dat [i,], dat [max (i, j), 2]) break } еще { out.I [[I]] <- data.frame (DAT [я,], DAT [макс (I, J), 2]) } } } Outi <- делать .call (rbind, out.i) colnames (outi) [3] <- "FieldNew" outi [3] <- ifelse (outi [, 2] == outi [, 3], "", as.character (Outi [3])) – Patrick