Página 1 de 1

Como retornar a segunda menor data

Enviado: Qui, 18 Out 2007 9:28 am
por brauliomsf
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

Enviado: Qui, 18 Out 2007 9:59 am
por rodfbar
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)

Enviado: Qui, 18 Out 2007 6:50 pm
por rogenaro
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

Enviado: Seg, 05 Nov 2007 1:10 pm
por Renan Orati
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!!

Enviado: Seg, 05 Nov 2007 6:57 pm
por rogenaro
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;

Enviado: Qui, 06 Dez 2007 12:41 pm
por Porva
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?!?!?!

Enviado: Qui, 06 Dez 2007 2:03 pm
por Tineks
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

Enviado: Qui, 06 Dez 2007 2:55 pm
por Porva
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! :(

Enviado: Qui, 06 Dez 2007 3:06 pm
por Tineks
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

Enviado: Qui, 06 Dez 2007 3:28 pm
por Porva
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.

Enviado: Qui, 06 Dez 2007 3:43 pm
por Porva
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

Enviado: Qui, 06 Dez 2007 5:27 pm
por Tineks
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

Enviado: Sex, 07 Dez 2007 7:57 am
por Porva
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????

Enviado: Sex, 07 Dez 2007 8:14 am
por Trevisolli
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.

Enviado: Sex, 07 Dez 2007 8:18 am
por Tineks
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

Enviado: Sex, 07 Dez 2007 8:29 am
por Porva
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:

Enviado: Sex, 07 Dez 2007 8:53 am
por Porva
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!

Enviado: Sex, 07 Dez 2007 10:24 am
por Porva
resolvi aqui Cristiano, só tirei o relacionamento da consulta interna com a externa, valeu pela paciência aí (y)

Enviado: Sex, 07 Dez 2007 10:32 am
por Tineks
Legal cara, desculpa a demora a responder, é q hj estou bem enrolado aqui. hehehehehe

[]'s!!!

Enviado: Sex, 07 Dez 2007 12:15 pm
por Porva
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

Re: Como retornar a segunda menor data

Enviado: Qui, 03 Out 2013 6:42 pm
por markosoftware
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);