2012-12-18 20 views
8

उदाहरण के लिए, मैं 2 समय टेबल है: टी 1कैसे ओरेकल एसक्यूएल में निकटतम दिनांकों पाने के लिए

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 

और टी 2

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

मैं टी 1 से बार हुआ है कि करीब हैं प्राप्त करने की आवश्यकता टी 2 से समय के लिए। इस टेबल के बीच कोई संबंध नहीं है। वह कुछ इस तरह होना चाहिए:

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 हिस्सा काम नहीं करेगा अन्यथा।

संपादित करें: स्वीकृति के लिए धन्यवाद, लेकिन नीचे बेन का उत्तर बेहतर है। यह ओरेकल विश्लेषणात्मक कार्यों का उपयोग करता है और बहुत बेहतर प्रदर्शन करेगा।

2

यहाँ यह एक का चयन करता है टी 1, है जहाँ से उस पंक्ति (रों)/टी 2 में किसी भी छोटी दूरी है:

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

यह टी 2.calldatetime-T1.calldatetime के बीच सबसे छोटा अंतर पाता है और T1.calldatetime की केवल एक पंक्ति प्राप्त करने के बजाय, यह वही नहीं है जो मुझे चाहिए। मुझे सभी पंक्तियों के लिए सबसे छोटी जरूरत है। – fen1ksss

+0

हम्म। तो आप T1 पंक्ति में प्रत्येक पंक्ति के लिए टी 2 में सबसे छोटे अंतर के साथ चाहते हैं? या टी 2 में प्रत्येक पंक्ति के लिए टी 1 में सबसे छोटा अंतर? टी 2 – pbhd

+0

धन्यवाद? यह काम करता हैं! – 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 

मूलतः, यह टी 1 में हर बार के बीच पूर्ण अंतर बाहर काम करता है और टी 2 तो टी 2 ID से छोटी से छोटी अंतर उठाता है; टी 1 से डेटा लौट रहा है।

यहां यह 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

में टी 2 में प्रत्येक पंक्ति के लिए – 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