Solucionado (ver solução)
Solucionado
(ver solução)
6
respostas

repetir data mais antiga por grupo

Estou com uma dificuldade em um case real. Vou tentar explicar num exemplo mais simples possivel. Fiz um select que me retorna o projeto e a data de cada despesa do projeto.

SELECT
    pro.descProj AS "PROJETO"
    , fin.dtNeg AS "DATA"
    , fin.vlrNeg AS "VALOR"
FROM
    TabelaFinanceira fin
    INNER JOIN TabelaProjeto pro ON pro.idProj = fin.idProj

o retorno é parecido com isso

ProjetoDataValor
R1001/01/2022500
R1001/02/2022500
R1001/03/2022500
R1101/02/2022500
R1101/03/2022500
R1101/04/2022500

O que estou tentando fazer é pegar a data minima de cada projeto e repetir na tabela, como no exemplo abaixo.

ProjetoDataValorInicio Projeto
R1001/01/202250001/01/2022
R1011/02/202250001/01/2022
R1021/03/202250001/01/2022
R1115/02/202250015/02/2022
R1121/03/202250015/02/2022
R1110/04/202250015/02/2022

Quando uso o MIN(fin.dtneg), me retorna somente a data minima de tudo, nao consigo repetir como no exemplo e nem separar por projeto, sei que deve ter algum tipo de subquery, group by, mas nao sei ainda como fazer. Alguém pode me ajudar nisso?

6 respostas

André,

Está dificil de montar um exemplo aqui, mas você precisa fazer isso:

  1. Agrupar o campo "Projeto" com um "Group By" deixando uma linha só para cada código de projeto;
  2. Pegar a menor data do agrupamento;

Vou chutar aqui, NÃO testei esta query, seria +/- assim:

SELECT
    pro.descProj AS "PROJETO"
    , MIN(fin.dtNeg) AS "DATA"
    , fin.vlrNeg AS "VALOR"
FROM
    TabelaFinanceira fin
    INNER JOIN TabelaProjeto pro ON pro.idProj = fin.idProj
GROUP BY
    pro.descProj

Abaixo alguns link para você ler:

==========================================================

Oracle GROUP BY

SELECT
    EXTRACT(YEAR FROM order_date) YEAR,
    COUNT( order_id )
FROM
    orders
GROUP BY
    EXTRACT(YEAR FROM order_date)
ORDER BY
    YEAR;

https://www.oracletutorial.com/oracle-basics/oracle-group-by/

==========================================================

Oracle MIN

SELECT
    category_name,
    MIN( list_price )
FROM
    products
INNER JOIN product_categories
        USING(category_id)
GROUP BY
    category_name
ORDER BY
    category_name;

https://www.oracletutorial.com/oracle-aggregate-functions/oracle-min/

==========================================================

SQL MIN() function with group by

SELECT cust_city, cust_country, MIN(outstanding_amt) 
FROM customer 
GROUP BY cust_country, cust_city;

https://www.w3resource.com/sql/aggregate-functions/min-with-group-by.php

==========================================================

SQL maior data de um registro antes da data determinada

SELECT cod_titulo, MAX(data_imp) 
FROM tb_importacao 
WHERE data_imp < '2015-04-13' AND situacao = 1
GROUP BY cod_titulo

https://pt.stackoverflow.com/questions/58826/sql-maior-data-de-um-registro-antes-da-data-determinada

==========================================================

Se não conseguir, me chama.

[]'s,

Fabio I.

André,

Acho que consegui montar um exemplo plausível... vou tentar explicar:

Imagine duas tabelas, com os seguintes campos e registros:

select *
from tb_projeto;

Tabela de Projetos

e

select *
from tb_departamento;

Tabela de Departamentos

Eu quero pegar a DATA do projeto mais ANTIGO de cada gerente.

Aqui o INNER JOIN sem nenhum tratamento:

select *
from tb_departamento d
inner join tb_projeto p
on d.NUMERO_DEPARTAMENTO = p.NUMERO_DEPARTAMENTO;

INNER JOIN entre Projeto e Departamento sem tratamento

Para fazer isso eu monto a seguinte query:

select d.CPF_GERENTE, min(p.data_inicio_projeto)
from tb_projeto p
inner join tb_departamento d
on d.NUMERO_DEPARTAMENTO = p.NUMERO_DEPARTAMENTO
group by d.CPF_GERENTE;

INNER JOIN entre Projeto e Departamento com tratamento

Desta forma isolei a data dos projetos mais antigos de cada gerente.

Seria isso?

Agora para QUEBRAR as pernas... eu quero além da menor "p.data_inicio_projeto" também o "p.numero_projeto" do respectivo projeto...

[]'s,

Fabio I.

Oi Fábio, muito obrigado pela explicação, porém não é bem isso....

Apesar de ter falado em agrupamento, foi com a ideia de, realmente, isolar a data minima, mas depois juntar e repetir nas linhas de cada projeto.

Meu objetivo final na verdade é fazer a contagem de dias, desde a data mais antiga MIN(fin.dtneg) até a data que foi gerado a despesa, que é a data de registro. Vou pegar a data e diminuir com data do inicio do projeto +1 pra chegar no resultado.

Não sei se tem alguma forma mais simples de fazer essa contagem. O resultado é exatamente como na tabela abaixo.

Esse é o resultado esperado.

ProjetoDataValorInicio ProjetocontagemDias
R1001/01/202250001/01/20221
R1011/02/202250001/01/202241
R1021/03/202250001/01/202279
R1115/02/202250015/02/20221
R1121/03/202250015/02/202234
R1110/04/202250015/02/202254

Talvez esse explicação agora mude tudo.. rsrs. Desculpe por nao explicar melhor o que queria.

solução!

Fábio, consegui...kkkkkk Lendo suas respostas resolvi tentar da seguinte forma...

Eu isolei a data minima por projeto, esse código me trouxe a data minima agrupada. Pra simplificar, vou tratar como se fosse apenas 1 tabela, esquece a tabela projeto. rsrs

SELECT 
    DESCPROJ AS "PROJETO"
    , MIN(DTNEG) AS "INICIO"
FROM 
    TABELAFINANCEIRA
GROUP BY
    DESCPROJ

Depois eu fiz o select da tabela normal e coloquei esse código acima como subquery. Fiz o JOIN e ABRACADABRA... KKKKKKKKKKKK Só fiz a operação matemática pra fazer a contagem de dias e deu certo.

SELECT
    FIN.DESCPROJ
    , FIN.DTNEG
    , FIN.VALOR
    , TBL_AUX.INICIO
    , (FIN.DTNEG - TBL_AUX.INICIO) +1 AS "CONTAGEM"
FROM
    (SELECT 
        DESCPROJ AS "PROJETO"
        , MIN(DTNEG) AS "INICIO"
    FROM 
        TABELAFINANCEIRA
    GROUP BY
        DESCPROJ) TBL_AUX
INNER JOIN TABELAFINANCEIRA FIN ON FIN.DESCPROJ = TBL_AUX.DESCPROJ

Lógico que o exemplo que dei foi bem mais simples que a realidade, mas fiquei tao feliz q posto o código real (retirei algumas colunas pra nao expor ninguem... rsrs)

SELECT
  CUS.DESCRCENCUS AS "PROJETO"
  , FIN.NUMNOTA AS "NOTA" 
  , FIN.DTNEG AS "DATA"
--  , PAR.NOMEPARC AS "PARCEIRO"
  , FIN.HISTORICO AS "DESCRIÇÃO"
--  , FIN.VLRDESDOB AS "VALOR"
  , PAR.CODPARC
--  , NAT.CODNAT
  , CONCAT (SUBSTR (NAT.CODNAT ,1,6), '00') AS "CODNAT"  
  , NAT.DESCRNAT AS "NATUREZA DESPESA"
  , NAT.CODNATPAI
--  , REPLACE (NAT.CODNATPAI, 30070100,30070000) AS "CODNAT"
  , CASE
      WHEN NAT.CODNAT LIKE '3001%' THEN 'MÃO DE OBRA'
      WHEN NAT.CODNAT LIKE '3003%' THEN 'DESPESAS ADMINISTRATIVAS'
      WHEN NAT.CODNAT LIKE '3005%' THEN 'MANUTENÇÕES EM GERAL'
      WHEN NAT.CODNAT LIKE '3009%' THEN 'IMPLEMENTOS AGRÍCOLAS'
      ELSE 'OUTROS'
    END AS "GRUPO NATUREZA DESPESA"
    , TBLAUX.INICIO
    , (FIN.DTNEG - TBLAUX.INICIO) +1 AS "CONTAGEM"

FROM
  TGFFIN FIN
  INNER JOIN TGFPAR PAR ON PAR.CODPARC = FIN.CODPARC
  INNER JOIN TGFNAT NAT ON NAT.CODNAT = FIN.CODNAT
  INNER JOIN TSICUS CUS ON CUS.CODCENCUS = FIN.CODCENCUS
  INNER JOIN
    (
      SELECT
        CUS.DESCRCENCUS AS "PROJETO"
        , MIN(FIN.DTNEG) AS "INICIO"
      FROM
        TGFFIN FIN
      INNER JOIN TSICUS CUS ON CUS.CODCENCUS = FIN.CODCENCUS
      GROUP BY
        CUS.DESCRCENCUS
    ) TBLAUX ON TBLAUX.PROJETO = CUS.DESCRCENCUS


WHERE
  NAT.CODNAT NOT IN (20040100) -- RETIRA NATUREZA 'INSUMOS AGRICOLAS' 
  AND CUS.CODCENCUSPAI = 20500 -- SELECIONA TODOS OS PROJETOS DA HIDROPONIA
  AND CUS.CODCENCUS <> 20501 -- TIRA O PROJETO R13


  AND (FIN.NURENEG IS NULL OR FIN.NURENEG < 0)


  AND FIN.DTNEG <= CURRENT_DATE  --TIRA AS DATAS DE LANÇAMENTOS FUTUROS

e também posto o resultado disso com a coluna que precisava... Resultado Case real Subquery

uhuuu... kkkkkk vlw Fábio, não foi exatamente a resposta que espera, mas foi melhor ainda, pois me fez pensar um pouco... Obrigado pelas dicas

André,

É isso! Que bom que conseguiu!

Deixa eu te falar.

Eu uso quatro sites de forums para tira essas dúvidas a saber:

  • VBMANIA (precisa assinar, mas é 100% grátis)

https://www.vbmania.com.br/index.php

  • MSDN (Site oficial da Microsoft)

https://social.msdn.microsoft.com/Forums/pt-BR/home

  • Code Project (Tem o fórum e a área de projketos bem interessantes)

https://www.codeproject.com/

  • Stackoverflow (Bem nojentinho, mas até funciona)

https://pt.stackoverflow.com/

https://stackoverflow.com/

[]'s,

Fabio I.