2012-12-18 250 views
8

例如,我有2個時間表: T1如何獲得在Oracle SQL最接近的日期

id time 
1 18:12:02 
2 18:46:57 
3 17:49:44 
4 12:19:24 
5 11:00:01 
6 17:12:45 

和T2

id time 
1 18:13:02 
2 17:46:57 

我需要從T1是最接近時間到T2的時間。這些表格之間沒有關係。 它應該是這樣的:

select T1.calldatetime 
from T1, T2 
where T1.calldatetime between 
T2.calldatetime-(
    select MIN(ABS(T2.calldatetime-T1.calldatetime)) 
    from T2, T1) 
and 
T2.calldatetime+(
    select MIN(ABS(T2.calldatetime-T1.calldatetime)) 
    from T2, T1) 

但我不能得到它。有什麼建議麼?

回答

4

我相信這是你要找的查詢:

CREATE TABLE t1(id INTEGER, time DATE); 
CREATE TABLE t2(id INTEGER, time DATE); 

INSERT INTO t1 VALUES (1, TO_DATE ('18:12:02', 'HH24:MI:SS')); 
INSERT INTO t1 VALUES (2, TO_DATE ('18:46:57', 'HH24:MI:SS')); 
INSERT INTO t1 VALUES (3, TO_DATE ('17:49:44', 'HH24:MI:SS')); 
INSERT INTO t1 VALUES (4, TO_DATE ('12:19:24', 'HH24:MI:SS')); 
INSERT INTO t1 VALUES (5, TO_DATE ('11:00:01', 'HH24:MI:SS')); 
INSERT INTO t1 VALUES (6, TO_DATE ('17:12:45', 'HH24:MI:SS')); 

INSERT INTO t2 VALUES (1, TO_DATE ('18:13:02', 'HH24:MI:SS')); 
INSERT INTO t2 VALUES (2, TO_DATE ('17:46:57', 'HH24:MI:SS')); 

SELECT t1.*, t2.* 
    FROM t1, t2, 
     ( SELECT t2.id, MIN (ABS (t2.time - t1.time)) diff 
      FROM t1, t2 
     GROUP BY t2.id) b 
WHERE ABS (t2.time - t1.time) = b.diff; 

確保時間列具有相同的日期部分,因爲t2.time - t1.time部分將無法正常工作除此以外。

編輯:感謝接受,但本的答案下面更好。它使用Oracle分析功能,並且性能會更好。

2

這裏這一次選擇從T1,它具有行(S)/在T2到任何的最小距離:

select T1.id, T1.calldatetime from T1, T2 
where ABS(T2.calldatetime-T1.calldatetime) 
     =(select MIN(ABS(T2.calldatetime-T1.calldatetime))from T1, T2); 

(與MySQL測試吧,希望你不要從得到一個ORA)

編輯:根據最後的評論,它應該是這樣的:

drop table t1; 
drop table t2; 
create table t1(id int, t time); 
create table t2(id int, t time); 

insert into t1 values (1, '18:12:02'); 
insert into t1 values (2, '18:46:57'); 
insert into t1 values (3, '17:49:44'); 
insert into t1 values (4, '12:19:24'); 
insert into t1 values (5, '11:00:01'); 
insert into t1 values (6, '17:12:45'); 

insert into t2 values (1, '18:13:02'); 
insert into t2 values (2, '17:46:57'); 

select ot2.id, ot2.t, ot1.id, ot1.t from t2 ot2, t1 ot1 
where ABS(ot2.t-ot1.t)= 
     (select min(abs(t2.t-t1.t)) from t1, t2 where t2.id=ot2.id) 

產地:

id  t  id  t 
1  18:13:02  1  18:12:02 
2  17:46:57  3  17:49:44 
+0

這個人發現T2.calldatetime-T1.calldatetime和得到T1.calldatetime只有一行之間的最小差異,這是不一樣的,我需要。我需要所有行中最小的。 – fen1ksss

+0

嗯。所以你想要T1中的每一行都有來自T2中最小差異的行嗎?或者T2中的每一行是T1中最小的差異? – pbhd

+0

在T2中的每一行T1中的最小差異 – fen1ksss

7

你只需要使用一個笛卡兒連接解決你不像其他的解決方案,它使用多個問題。我假設時間存儲爲VARCHAR2。如果它被存儲爲一個日期,那麼你可以刪除TO_DATE功能。如果(我會極力推薦這)存儲爲一個日期,你將需要刪除的日期部分

我做了稍微詳細所以很明顯這是怎麼回事。

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 

基本上,這工作進行每一次之間的絕對差在T1和T2然後拾取由T2 ID最小差值;從T1返回數據。

這是SQL Fiddle format

的非常少(但更短)的格式是:

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 
+0

謝謝?有用! – fen1ksss

1

嘗試此查詢它的小長篇,我會盡力去優化它

select * from t1 
where id in (
select id1 from 
(select id1,id2, 
rank() over (partition by id2 order by diff) rnk 
from 
(select distinct t1.id id1,t2.id id2, 
round(min(abs(to_date(t1.time,'HH24:MI:SS') - to_date(t2.time,'HH24:MI:SS'))),2) diff 
from 
t1,t2 
group by t1.id,t2.id)) 
where rnk = 1); 
2

使用分析功能的另一種方式。 可能奇怪:)

select id, time, 
case 
    when to_date(time, 'hh24:mi:ss') - to_date(lag_time, 'hh24:mi:ss') < to_date(lead_time, 'hh24:mi:ss') - to_date(time, 'hh24:mi:ss') 
    then lag_time 
    else lead_time 
    end closest_time 
from (
select id, tbl, 
    LAG(time, 1, null) OVER (ORDER BY time) lag_time, 
    time, 
    LEAD(time, 1, null) OVER (ORDER BY time) lead_time 
from 
    (
    select id, time, 1 tbl from t1 
    union all 
    select id, time, 2 tbl from t2 
) 
) 
where tbl = 2 

SQLFiddle ......和超越!

+0

+1爲滯後和鉛,非常有用的功能 – chrismarx