Ir para conteúdo
Fórum Script Brasil

Gildecy Júnior Lisboa Calabró

Membros
  • Total de itens

    3
  • Registro em

  • Última visita

Sobre Gildecy Júnior Lisboa Calabró

Gildecy Júnior Lisboa Calabró's Achievements

0

Reputação

  1. Encontrei a solução. Fiz uma query utilizando a função generate_series() para gerar datas entre os períodos para cada um dos cargos listados. Ordenei e fiz um case para determinar que quando houvessem datas iguais para os dois tipos de cargo, que trouxesse somente o do cargo predominante, que seria VP quando não houvesse, traz o cargo de DI. Com isso consegui montar a linha do tempo detalhada, data a data. Para resumir isso da forma que estava somente com data início e data fim, tive que utilizar função e armazenar os dados em variáveis para fazer inserts e updates no banco. Segue o script que fiz, creio que ainda caiba melhorias: --CRIANDO OU REGRIANDO A FUNÇÃO CREATE OR REPLACE FUNCTION f_gera_linha_tempo( --LOCAL PARA DECLARAR PASSAGEM DE PARÂMETROS ) RETURNS bigint LANGUAGE 'plpgsql' COST 100 VOLATILE PARALLEL UNSAFE AS $BODY$ DECLARE --DECLARANDO AS VARIÁVEIS VFuncao CHARACTER VARYING(100); VFuncaoAux CHARACTER VARYING(100); VNuFuncao INTEGER; VNuFuncaoAux INTEGER; i INTEGER; rec_linha RECORD; BEGIN --INICIALIZANDO AS VARIÁVEIS VFuncao = ''; VFuncaoAux = ''; VNuFuncao = 0; VNuFuncaoAux = 0; i = 0; --DELETA OS DADOS DA TABELA PARA RECRIAR COM A FUNÇÃO DELETE FROM tb_linha_tempo; --INICIA LOOP FOR rec_linha IN --CONSULTA QUE CARREGA OS REGISTROS DO LOOP /* A CONSULTA IRÁ EXPANDIR OS PERÍODOS DIA A DIA USANDO GENERATE_SERIES PARA PODER ISOLAR OS DIAS QUE SERÃO DESCONSIDERADOS NA SOBREPOSIÇÃO, MANTENDO SOMENTE OS DIAS QUE DEVERÃO SER CONSIDERADOS NA MONTAGEM DA LINHA DO TEMPO CADASTRO: (o que eu tenho) DI1 = 01/01/2023 A 31/03/2023 VP1 = 10/01/2023 A 20/01/2023 VP2 = 10/02/2023 A 20/03/2023 DI2 = 01/04/2023 A 10/04/2023 */ WITH funcoes AS ( SELECT ROW_NUMBER() OVER (ORDER BY r.datas) AS sequencia, r.no_funcao, r.datas FROM ( SELECT DISTINCT a.no_funcao, CASE WHEN SUBSTRING(a.no_funcao,1,2) = 'DI' THEN 1 ELSE 2 END AS cod_funcao, generate_series( a.dt_inicio::DATE, DATE(a.dt_fim - INTERVAL '1 DAY')::DATE, '1 day')::DATE AS datas FROM tb_funcoes AS a ) AS r ORDER BY datas ), menor_funcao AS ( SELECT no_funcao, datas, MIN(cod_funcao) AS cod_funcao FROM funcoes GROUP BY 1,2 ) SELECT dir.no_funcao, dir.datas FROM funcoes AS dir INNER JOIN menor_funcao AS mo ON mo.cod_funcao = dir.cod_funcao AND mo.no_funcao = dir.no_funcao AND mo.datas = dir.datas ORDER BY dir.datas --COMEÇA A EXECUTAR O LOOP LOOP --VARIÁVEIS PRINCIPAIS RECEBEM OS VALORES VFuncao = rec_linha.no_funcao; VNuFuncao = rec_linha.cod_funcao; --SE AS VARIÁVEIS PRINCIPAIS FOREM DIFERENTES DAS AUXILIARES, ENTRA NA CONDIÇÃO IF (VFuncao != VFuncaoAux AND VNuFuncao != VNuFuncaoAux) THEN i = i + 1; --VARIÁVEL QUE SERVIRÁ DE ID NA TABELA --VARIÁVEIS AUXILIARES RECEBEM O MESMO VALOR DA VARIÁVEL PRINCIPAL VFuncaoAux = rec_linha.no_funcao; VNuFuncaoAux = rec_linha.cod_funcao; --INSERE LINHA NA TABELA COM DATA FIM AINDA NULA INSERT INTO tb_linha_tempo(id_linha, no_funcao, dt_inicio,dt_fim, cod_funcao) VALUES (i, rec_linha.no_funcao, rec_linha.datas, null, rec_linha.cod_funcao); ELSE --SE OCORRÊNCIA PRINCIPAL DIFERENTE DA AUXILIAR, ENTRA NA CONDIÇÃO IF (VNuFuncao != VNuFuncaoAux) THEN --VARIÁVEL AUXILIAR RECEBE O VALOR DA OCORRÊNCIA VNuFuncaoAux = rec_linha.cod_funcao; i = i + 1; --INCREMENTA O ID --INSERE LINHA NA TABELA INSERT INTO tb_linha_tempo(id_linha, no_funcao, cod_funcao) VALUES (i, rec_linha.no_funcao, rec_linha.datas, null, rec_linha.cod_funcao); ELSE --FICA ATUALIZANDO A DATA FIM ATÉ QUE O LOOP MUDE DE OCORRÊNCIA, A ÚLTIMA DATA A SER ATULIZADA É A QUE FECHA O PERÍODO UPDATE tb_linha_tempo SET dt_fim = rec_linha.datas WHERE id_linha = i; END IF; --segundo SE END IF; --primeiro SE END LOOP; --ATUALIZA A DATA FIM DAS LINHAS COM DT_FIM NULA --A DT_FIM FICA NULA QUANDO SÓ EXISTE UM REGISTRO DE DATA PARA A OCORRÊNCIA DO EMPREGADO UPDATE tb_linha_tempo SET dt_fim = dt_inicio WHERE dt_fim IS NULL; RETURN 0; END; $BODY$; ALTER FUNCTION f_gera_linha_tempo() OWNER TO postgres; -- SELECT f_gera_linha_tempo() -- DROP FUNCTION f_gera_linha_tempo() -- SELECT * FROM tb_linha_tempo ORDER BY 1 -- DELETE FROM tb_linha_tempo
  2. seriam cargos, DI = diretoria e VP = vice-presidencia ocorre que o período como VP tem predominância sobre o período de DI. DI1 seia o primeiro período dele como diretor de um departamento X e DI2 seria o período como diretor do departamento Y por exemplo. Porque ele pode ser diretor de departamentos diferentes durante a linha do tempo e também pode ter sido VP em vice-presidencias diferentes na empresa. Por isso a necessidade de criar cortes na linha do tempo de DI para considerar o período como VP, quando acabar o período de VP volta a contar o período de DI.
  3. Preciso montar uma linha do tempo onde os períodos de VP possuem predominância sobre os períodos de DI, porém quando não houver período de VP e ainda estiver dentro do período de DI, esse período de DI deve ser contabilizado até que termine ou até que haja outro período de VP. Caso nenhum período de VP esteja sobrepondo o período de DI, segue-se a ordem normal do cadastro. Necessito de uma consulta que exiba ou uma função que grave essa linha do tempo em uma tabela. São 3 colunas na tabela: |Funcão | Data Inicio | Data Fim | | DI1 |01/01/2023|31/03/2023| | DI2 |10/01/2023|20/01/2023| | VP1 |10/02/2023|20/03/2023| | VP2 |01/04/2023|10/04/2023| CADASTRO: (o que eu tenho) DI1 = 01/01/2023 A 31/03/2023 VP1 = 10/01/2023 A 20/01/2023 VP2 = 10/02/2023 A 20/03/2023 DI2 = 01/04/2023 A 10/04/2023 LINHA DO TEMPO: (como deve ficar) DI1 = 01/01/2023 A 09/01/2023 VP1 = 10/01/2023 A 20/01/2023 DI1 = 21/01/2023 A 09/02/2023 VP2 = 10/02/2023 A 20/03/2023 DI1 = 21/03/2023 A 31/03/2023 DI2 = 01/04/2023 A 10/04/2023 Já queimei todos os dois neurônios e não consegui chegar em uma solução. Se alguém tiver uma solução ou uma luz de como posso fazer isso, ficarei grato.
×
×
  • Criar Novo...