Você só precisa usar uma única junção cartesiana para resolver seu problema, ao contrário das outras soluções, que usam várias. Presumo que o tempo seja armazenado como um VARCHAR2. Se estiver armazenado como uma data, você poderá remover as funções TO_DATE. Se for armazenado como uma data (eu recomendo isso), você terá que remover as partes da data
Eu fiz isso um pouco detalhado, então é óbvio o que está acontecendo.
select *
from ( select id, tm
, rank() over ( partition by t2id order by difference asc ) as rnk
from ( select t1.*, t2.id as t2id
, abs( to_date(t1.tm, 'hh24:mi:ss')
- to_date(t2.tm, 'hh24:mi:ss')) as difference
from t1
cross join t2
) a
)
where rnk = 1
Basicamente, isso calcula a diferença absoluta entre todas as vezes em T1 e T2 e, em seguida, seleciona a menor diferença por T2
ID
; retornando os dados de T1. Aqui está em formato SQL Fiddle .
O formato menos bonito (mas mais curto) é:
select *
from ( select t1.*
, rank() over ( partition by t2.id
order by abs(to_date(t1.tm, 'hh24:mi:ss')
- to_date(t2.tm, 'hh24:mi:ss'))
) as rnk
from t1
cross join t2
) a
where rnk = 1