Como retornar a segunda menor data

Dúvidas, dicas e truques de SQL, Select, Update, Delete, cláusulas, operações com joins, Funções em SQLs, etc
brauliomsf
Rank: Estagiário Sênior
Rank: Estagiário Sênior
Mensagens: 9
Registrado em: Qui, 18 Out 2007 9:18 am
Localização: SP
Braulio Moizes

Tenho uma tabela com código e data, onde o codigo se repete para datas distintas.
Se eu fizer o min(data), codigo eu obtenho a menor data por codigo.
Mas eu preciso da segunda menor data.
A principio fiz um select retornando a menor data dentro de um select usando not in e em seguinda o select principal retornando a 2º menor data exemplo:

Selecionar tudo

select min(data),codigo
 from tabela
where codigo in (select codigo
                 from tabela
                 where codigo not in (select a.codigo
                                      from tabela a
                                      where data in (select min(b.data)
                                                     from tabela b
                                                     where  b.codigo =  a.codigo)
Existe alguma maneira mais simples de retornar a 2º menor data?????

Grato
rodfbar
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 241
Registrado em: Ter, 09 Out 2007 11:15 am
Localização: Batatais - SP

tenta ai

Selecionar tudo

select  min(a.data),a.codigo 
  from  tabela a
 where  a.data > (select min(b.data)
                            from tabela b
                          where b.codigo = a.codigo)
rogenaro
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 232
Registrado em: Sex, 30 Mar 2007 7:26 pm
Localização: Londrina - PR
Rafael O. Genaro

Pelo que entendi da sua consulta, você está retornando todos os códigos com a segunda menor data da tabela, certo?

Selecionar tudo

select codigo
     , data
from
(
  select t.codigo
       , t.data
       , dense_rank() over (order by t.data asc) posicao
  from   tabela t
) 
where  posicao = 2
;
Não tenho como testar essa query no momento, mas acredito que funcione :D
Renan Orati
Rank: Analista Júnior
Rank: Analista Júnior
Mensagens: 90
Registrado em: Qui, 23 Ago 2007 3:40 pm
Localização: São José do Rio Preto - SP

kara... acho que o "ROWNUM" também DA PRA FAZER... TENTA aí!

Selecionar tudo

select codigo, data
  from (select t.codigo, t.data, rownum posicao
          from tabela t
         order by t.data asc)
 where posicao = 2;
falou!!
rogenaro
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 232
Registrado em: Sex, 30 Mar 2007 7:26 pm
Localização: Londrina - PR
Rafael O. Genaro

kara... acho que o "ROWNUM" também DA PRA FAZER... TENTA aí!

Código:

Selecionar tudo

select codigo, data 
  from (select t.codigo, t.data, rownum posicao 
          from tabela t 
         order by t.data asc) 
 where posicao = 2; 
falou!!
Só uma correção:
o rownum é gerado antes da execução da cláusula order by, portanto o registro retornado pode não ser a segunda menor data... Seria necessário adicionar mais um nível na consulta:

Selecionar tudo

select codigo, data 
from  
( 
  select rownum posicao, a.*
  from 
  (
    select t.codigo, t.data
    from   tabela t 
    order by t.data asc
  ) a
) 
where posicao = 2;
Avatar do usuário
Porva
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 342
Registrado em: Seg, 29 Jan 2007 7:36 am
Localização: São Paulo/SP
Rafael S. Nunes
São Paulo/SP

pessoal, estou com uma dúvida em relação a datas num Select, e estou postando aqui pra não criar um novo tópico só pra isso:

esse será minha select interna:

Selecionar tudo

SELECT Max(g.lora_dt) Ultima_Ligacao
  FROM gelogramal g, rhfunc
 WHERE g.func_cd = rhfunc.func_cd
   AND g.empr_cd = rhfunc.empr_cd
   AND g.inra_ddd = '43'
   AND g.inra_nr = '33210710'
   AND g.lora_dt NOT BETWEEN To_Date('01/12/2007','DD/MM/YYYY')
                      AND To_Date('30/12/2007','DD/MM/YYYY');
ela me retorna:

ULTIMA_LIGACAO
10/09/2007 12:00:00

Se eu coloco ela nesse SQL, me retorna 2 registros(!?)

Selecionar tudo

SELECT rhpessoa.pess_nm_nome,
       rhfunc.func_cd,
       gelogramal.lora_dt
  FROM rhpessoa, rhfunc, gelogramal
 WHERE rhfunc.pess_cd = rhpessoa.pess_cd
   AND gelogramal.func_cd = rhfunc.func_cd
   AND gelogramal.empr_cd = rhfunc.empr_cd
   AND gelogramal.inra_ddd = '43'
   AND gelogramal.inra_nr = '33210710'
   AND gelogramal.lora_dt NOT BETWEEN To_Date('01/12/2007','DD/MM/YYYY')
                                  AND To_Date('30/12/2007','DD/MM/YYYY') 

   AND gelogramal.lora_dt = (SELECT Max(g.lora_dt) Ultima_Ligacao
	                       FROM gelogramal g
	                      WHERE g.func_cd = rhfunc.func_cd
	                        AND g.empr_cd = rhfunc.empr_cd
	                        AND g.inra_ddd = gelogramal.inra_ddd
	                        AND g.inra_nr = gelogramal.inra_nr
	                        AND g.lora_dt NOT BETWEEN To_Date('01/12/2007','DD/MM/YYYY')
			                                              AND To_Date('30/12/2007','DD/MM/YYYY'))


	   AND gelogramal.lora_bo_particular = 'S';

Selecionar tudo

FULANO 1   01/09/2007 10:04:00
FULANO 2   10/09/2007 12:00:00 --Deveria retornar somente esse registro! (maior data)
porque isso acontece?!, ora, se a Select interna retorna a maior data (SELECT Max(g.lora_dt) Ultima_Ligacao), porque a comparação não está funcioando nesse caso?!?!?!
Tineks
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 365
Registrado em: Ter, 24 Mai 2005 2:24 pm
Localização: Araraquara - SP
Cristiano (Tineks)
Araraquara - SP

E ai Porva,

cara pelo q eu entendi seu select principal lê uma tabela de funcionarios, e a subconsulta q existe no where dela está amarrada ao funcionario tb.. dessa forma será exibido mais de um registro.... será q não é isso?

[]'s
Avatar do usuário
Porva
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 342
Registrado em: Seg, 29 Jan 2007 7:36 am
Localização: São Paulo/SP
Rafael S. Nunes
São Paulo/SP

Cristiano, retirei aqui a comparação de funcionário e empresa e funcinou, mas eu tenho poucos registros nesse caso, meu medo é: eu não preciso relacionar o Select interno com o externo??? o select interno não vai me trazer um max(data) de outro registro que não tenha nada a ver?, não saquei bem a lógica do mecanismo! :(
Tineks
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 365
Registrado em: Ter, 24 Mai 2005 2:24 pm
Localização: Araraquara - SP
Cristiano (Tineks)
Araraquara - SP

Então, eu não entendi o q você realmente precisa..
essa sua consulta deve buscar todos os funcionários e trazer a maior data de cada um ou somente a maior data entre todos??

[]'s
Avatar do usuário
Porva
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 342
Registrado em: Seg, 29 Jan 2007 7:36 am
Localização: São Paulo/SP
Rafael S. Nunes
São Paulo/SP

a maior data entre todos

deixa eu tentar ser mais claro e explicar a bagunça:


eu tenho o controle de ramais que funciona da seguinte forma, quando a ligação for particular do funcionário, a empresa cobra por ela, imagine que no período de 01/09/2007 a 30/09/2007 o funcionário FABIO e o funcionário RAFAEL ligaram para um telefone que não é um contato da empresa, um amigo deles por exemplo cujo número do telefone é: 43
33334444:

eles ligaram na seguinte data/seqüência:

Selecionar tudo

Nome    Data           Nº tel
----------------------------------------
FABIO   01/09/2007     43 33334444
RAFAEL  10/09/2007     43 33334444

quando o usuário pedir um filtro das ligações do mês de Dezembro/2007, novamente eu verifico

se existem registros desse telefone externo (43 33334444) FORA do período informado e com funcionário já relacionado*, procurando ocorrências de funcionários que já estejam relacionados a esse número, aí no bloco tabular eu já traria esse funcionário com uma cor diferente sugerindo que aquele número pertence a ele, o que quero é trazer um funcionário apenas, no caso, o último que ligou pra esse número.

dae eu pensei em fazer um Select que retorne o a última ligação feita pro telefone (43 33334444) e que esteja com o funcioário já relacionado lá atrás, no mês de Setembro


*o chefe do depto relaciona o funcionário da seguinte forma, os registros são exibidos num bloco multirecord, e passa uma lista no papel mesmo, pelo depto pra cada funcinário identificar suas ligações, aí o usuário (no sistema) amarra essas ligações aos funcionários.
Avatar do usuário
Porva
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 342
Registrado em: Seg, 29 Jan 2007 7:36 am
Localização: São Paulo/SP
Rafael S. Nunes
São Paulo/SP

olha aí Cristiano, pra ficar mais visual a coisa

quando eu pedir o intervalo de dezembro (01 a 31), ele novamente terá esse telefone '33210710', dae eu trago automaticamente o último funcionário que ligou pra ele, no caso, eu mesmo no exemplo..

Imagem
Tineks
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 365
Registrado em: Ter, 24 Mai 2005 2:24 pm
Localização: Araraquara - SP
Cristiano (Tineks)
Araraquara - SP

E ai Porva, beleza??
cara, da uma olhada nesse codigo, vê se é +- isso..

Selecionar tudo

SQL> select * from mens_erro;

NOME                                     DATA      TEL
---------------------------------------- --------- ---------------
Fabio                                    01-SEP-07 43 33334444
Rafael                                   10-SEP-07 43 33334444

SQL> SELECT a.*, nvl2(b.maxdata,'Ultimo',null) flag
  2    FROM mens_erro a,
  3         (SELECT MAX (DATA) maxdata
  4            FROM mens_erro) b
  5   WHERE a.DATA BETWEEN TO_DATE ('01/09/2007', 'DD/MM/YYYY')
  6                    AND TO_DATE ('30/09/2007', 'DD/MM/YYYY')
  7     AND a.data = b.maxdata(+)
  8  /

NOME                                     DATA      TEL             FLAG
---------------------------------------- --------- --------------- ------
Rafael                                   10-SEP-07 43 33334444     Ultimo
Fabio                                    01-SEP-07 43 33334444
[]'s
Avatar do usuário
Porva
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 342
Registrado em: Seg, 29 Jan 2007 7:36 am
Localização: São Paulo/SP
Rafael S. Nunes
São Paulo/SP

Cristiano, eu que tava com a cabeça quente ontem e não tava conseguindo pensar direito!, fiz do jeito simples mesmo, tipo, como eu tava relacionando funcionário da consulta interna com a externa, e tava trazendo mais de um registro por isso, simplesmente fiz as duas consultas praticamente idênticas, mas a interna com MAX e relacionando na próprio consulta com funcionário:

Selecionar tudo

SELECT rhpessoa.pess_nm_nome,
		 rhfunc.func_cd,
		 gelogramal.lora_dt
  FROM rhpessoa, rhfunc, gelogramal
 WHERE rhfunc.pess_cd = rhpessoa.pess_cd
   AND gelogramal.func_cd = rhfunc.func_cd
   AND gelogramal.empr_cd = rhfunc.empr_cd
   AND gelogramal.lora_dt = (  SELECT Max(g.lora_dt)
       	                       FROM gelogramal g, rhfunc f --relacionei internamente RHFUNC
      	                       WHERE g.func_cd  = f.func_cd
      	                         AND g.empr_cd  = f.empr_cd
      	                         AND g.inra_ddd = '43'
      	                         AND g.inra_nr  = '33210710'
      	                         AND g.lora_bo_particular = 'S'
      	                         AND g.lora_dt NOT BETWEEN TO_DATE('01/12/2007','DD/MM/YYYY')
      	                                               AND TO_DATE('30/12/2007','DD/MM/YYYY') );

agora uma curiosidade, como o Oracle procede nesse caso, ele executa a consulta interna primeiro????
Trevisolli
Moderador
Moderador
Mensagens: 2016
Registrado em: Qua, 12 Jan 2005 3:25 pm
Localização: Araraquara - SP
Abraço,

Trevisolli
OCA Oracle PL/SQL Developer Certified Associate
OCP Oracle Forms Developer Certified Professional
Araraquara-SP

Então Porva, beleza cara?

Seguinte, creio que, não é que ele LÊ primeiro o interno mas, creio que ele inicialize o Parse, de baixo para cima.

Me corrijam se eu estiver errado.
Tineks
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 365
Registrado em: Ter, 24 Mai 2005 2:24 pm
Localização: Araraquara - SP
Cristiano (Tineks)
Araraquara - SP

E ai Porva, beleza?

Cara, na subconsulta você colocou a tabela rhfunc, ela está se relacionando com a gelogramal, porem esse relacionamento eu acho desnecessário pois você não está fazendo nenhum filtro na rhfunc, e tb não esta utilizando nenhum campo dela com a consulta externa....
Agora fique com uma duvida, sobre esse trecho aqui.

Selecionar tudo

... AND gelogramal.lora_dt = (  SELECT Max(g.lora_dt) ...
fazendo dessa forma você só vai trazer o ultimo usuário que fez a ligação!!!???... é isso mesmo? ou teria q ser um outer join nesse ponto.

[]'s
Avatar do usuário
Porva
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 342
Registrado em: Seg, 29 Jan 2007 7:36 am
Localização: São Paulo/SP
Rafael S. Nunes
São Paulo/SP

puts, é verdade cara, viajei de novo!

e sim, eu só preciso trazer 1 funcionário mesmo, o último que ligou 'MAX(data)'

então, isso que está fo*a de sacar, porque se eu relacino a consulta interna com a externa, aí cai naquele caso de trazer mais de 1 funcionário, e isso não pode acontecer

esqueçam meu SQL aí do post acima, está errado :roll:
Avatar do usuário
Porva
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 342
Registrado em: Seg, 29 Jan 2007 7:36 am
Localização: São Paulo/SP
Rafael S. Nunes
São Paulo/SP

eu até tentei um:

Selecionar tudo

SELECT rhpessoa.pess_nm_nome,
       rhfunc.func_cd,
       gelogramal.lora_dt
  FROM rhpessoa, rhfunc, gelogramal
 WHERE rhfunc.pess_cd = rhpessoa.pess_cd
   AND gelogramal.func_cd = rhfunc.func_cd
   AND gelogramal.empr_cd = rhfunc.empr_cd
   AND gelogramal.inra_ddd = '43'
   AND gelogramal.inra_nr  = '33210710'
   AND gelogramal.lora_bo_particular = 'S'
   AND gelogramal.lora_dt NOT BETWEEN To_Date('01/12/2007','DD/MM/YYYY')
                                  AND To_Date('30/12/2007','DD/MM/YYYY')
   AND ROWNUM < 2
 ORDER BY gelogramal.lora_dt DESC;
mas ele executa o ROWNUM antes do ORDER BY, aí fica na mesma!
Avatar do usuário
Porva
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 342
Registrado em: Seg, 29 Jan 2007 7:36 am
Localização: São Paulo/SP
Rafael S. Nunes
São Paulo/SP

resolvi aqui Cristiano, só tirei o relacionamento da consulta interna com a externa, valeu pela paciência aí (y)
Tineks
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 365
Registrado em: Ter, 24 Mai 2005 2:24 pm
Localização: Araraquara - SP
Cristiano (Tineks)
Araraquara - SP

Legal cara, desculpa a demora a responder, é q hj estou bem enrolado aqui. hehehehehe

[]'s!!!
Avatar do usuário
Porva
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 342
Registrado em: Seg, 29 Jan 2007 7:36 am
Localização: São Paulo/SP
Rafael S. Nunes
São Paulo/SP

o loco meo, que isso, hehe, tu foi prestativo pra caramba, valeu mais uma vez

perguntei prum cara bozão do SQL que trabalha aqui mas que estava de férias :)

eu pensei que deveria ter essa ligação entre os dois selects, mas não :S
markosoftware
Rank: Estagiário Júnior
Rank: Estagiário Júnior
Mensagens: 1
Registrado em: Sáb, 14 Set 2013 2:36 pm

Boa noite,,, cara não sei se entedi muito bem... mais segue um exemplo com uma logica bem simples de como retornar a segunda maior data ou vlr,,

Selecionar tudo

select max(data) from tabela where  data > (select max(data) from tabela);
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 7 visitantes