11

たとえば、2 つのタイム テーブルがあります: T1

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

T2 からの時間に最も近い T1 から時間を取得する必要があります。このテーブル間に関係はありません。次のようになります。

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

5 に答える 5

9

複数を使用する他のソリューションとは異なり、問題を解決するには、単一のデカルト結合を使用するだけで済みます。時間は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からデータを返します。

ここでは、SQLFiddle形式です

あまりきれいではない(しかし短い)形式は次のとおりです。

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
于 2012-12-18T08:59:19.630 に答える
5

これがあなたが探しているクエリだと思います:

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の分析関数を使用しており、パフォーマンスが大幅に向上します。

于 2012-12-18T08:56:36.457 に答える
2

分析関数を使用するもう 1 つの方法。奇妙かもしれません:)

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へ...そしてその先へ!

于 2012-12-18T12:50:49.493 に答える
2

ここでは、T1 から、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
于 2012-12-18T08:49:15.537 に答える
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);
于 2012-12-18T09:14:35.743 に答える