Para uma carga inicial dos dados, a consulta que o rodfbar postou no início já resolveria (faça primeiro a carga o campo sequencia preenchido com qualquer valor no primeiro passo, e em seguida faça a consulta):
Selecionar tudo
select p.*
, row_number() over ( partition by id_produtosprecos, tipopreco, filial
order by validadefim nulls last
) rn
from vw_produtosprecos p
Veja se a ultima coluna (rn) retorna a numeração da sequencia que você espera.
Pelo que entendi:
A menor data de validade fim recebe a menor sequencia (1), que é incrementada de 1 em 1 conforme a data de validade fim aumenta.
Datas não informadas (null), devem possuir a maior sequencia do grupo.
A cada alteração em id_produtosprecos, tipopreco ou filial, a seqencia derá ser reiniciada a partir do número 1.
(só para confirmar, pois no seu ultimo exemplo o código da antepenultima linha é 585880 com sequencia 1.. já o código seguinte, 585881, inicia na sequencia 2... ficou meio estranho neste ponto.. a antepenultima linha deveria ter o código 585881 também, ou a penultima linha deveria ter sequencia 1 e a ultima sequencia 2? Ou eu entendi a regra errado?)
Se estiver tudo OK, é só atualizar os dados conforme o comando abaixo (versão 9i ou superior)
Selecionar tudo
merge into vm_produtosprecos p
using ( select rowid rid
, row_number() over ( partition by id_produtosprecos, tipopreco, filial
order by validadefim nulls last
) rn
from vw_produtosprecos
) p2
on ( p.rowid = p2.rid )
when matched then
update
set p.sequencia = p2.rn
;
Agora, para reorganizar as sequencias sem alterar o programa (que seria o ideal), é possível realizar via triggers também, mas fica um pouco mais trabalhoso...
Selecionar tudo
-- Primeiro criamos uma package para armazenar as chaves dos registros que foram alterados
create or replace package k_produtosprecos as
type pp_rec is record
( id_produtosprecos vw_produtosprecos.id_produtosprecos%type
, tipopreco vw_produtosprecos.tipopreco%type
, filial vw_produtosprecos.filial%type
);
type pp_tab is table of pp_rec index by binary integer;
t_pp pp_tab;
end k_produtosprecos;
/
-- Em seguida, uma trigger before inset/update (statement level), para limpar os dados utilizados por outras execuções
create or replace trigger t_vm_produtosprecos_biu before insert or update on vm_produtosprecos as
begin
k_produtosprecos.t_pp.delete;
end t_vm_produtosprecos_bi;
/
-- Agora, uma trigger before insert/update (row level), para armazenar os conjuntos de id, tipo e filial que foram inseridos/alterados
create or replace trigger t_vm_produtosprecos_biur before insert or update on vm_produtosprecos for each row as
declare
i number;
begin
i := k_produtosprecos.t_pp.count() + 1;
k_produtosprecos.t_pp(i).id_produtosprecos := :new.id_produtosprecos;
k_produtosprecos.t_pp(i).tipopreco := :new.tipopreco;
k_produtosprecos.t_pp(i).filial := :new.filial;
end t_vm_produtosprecos_biur;
/
-- Finalmente, uma trigger after insert/update (statement level), para realizar o processamento.
-- Este tipo de trigger não dispara o erro mutating table, pois ela é disparada apenas uma vez para
-- o comando (como não é possível acessar os valores :new ou :old, precisamos da package para armazenar
-- estas informações)
create or replace trigger t_vm_produtosprecos_aiu after insert or update on vm_produtosprecos as
begin
if ( k_produtosprecos.t_pp.count() > 0 ) then
for i in k_produtosprecos.t_pp.first .. k_produtosprecos.t_pp.last loop
merge into vm_produtosprecos p
using ( select rowid rid
, row_number() over ( partition by id_produtosprecos, tipopreco, filial
order by validadefim desc nulls first
) rn
from vw_produtosprecos
where id_produtosprecos = k_produtosprecos.t_pp(i).id_produtosprecos
and tipopreco = k_produtosprecos.t_pp(i).tipopreco
and filial = k_produtosprecos.t_pp(i).filial
) p2
on ( p.rowid = p2.rid )
when matched then
update
set p.sequencia = p2.rn
;
end loop;
end if;
k_produtosprecos.t_pp.delete;
end t_vm_produtosprecos_aiu;