テーブルは2つあります:tbl1、tbl2。
CREATE TABLE tbl1(time_1)
AS VALUES
( '2017-09-06 15:26:03'::timestamp ),
( '2017-09-06 15:26:02' ),
( '2017-09-06 15:28:01' ),
( '2017-09-06 15:40:00' );
CREATE TABLE tbl2(time_2)
AS VALUES
( '2017-09-06 15:29:01'::timestamp ),
( '2017-09-06 15:40:00' ),
( '2017-09-06 15:23:59' ),
( '2017-09-06 15:45:58' );
テーブルに参加したいので、tbl1のすべての行がtbl2の最も近い時間に一致します。出力は次のとおりです。
time_1 time_2
--------------------- --------------------
2017-09-06 15:26:03 2017-09-06 15:23:59
2017-09-06 15:26:02 2017-09-06 15:23:59
2017-09-06 15:28:01 2017-09-06 15:29:01
2017-09-06 15:40:00 2017-09-06 15:45:58
私は最も近い時間の単一の値を見つける方法を知っています:
SELECT * from tbl1 where time_1=INPUT_TIME ORDER BY case when time_1 > INPUT_TIME then time_1 - INPUT_TIME else INPUT_TIME - time_1 end limit 1;
btree_Gist
および<->
の使用あなたは本当に<->
が必要です。これは内部tstz_dist
を通じてGistインデックスで実際に機能します。あなたは本当に間隔を気にしないので、これはうまくいきます。まず、拡張子を追加する必要があります。
CREATE EXTENSION btree_Gist;
その後
SELECT DISTINCT ON (time_1) time_1, time_2
FROM tbl1
CROSS JOIN tbl2
ORDER BY time_1, time_1 <-> time_2;
行が多すぎてクロス結合を実行できない場合は、ラテラルソリューションの方がうまくいく場合があります。
SELECT time_1, time_2
FROM tbl1
CROSS JOIN LATERAL (
SELECT time_2
FROM tbl2
ORDER BY time_1<->time_2
LIMIT 1
) AS tbl2;
ベンチマークに関するレポートを確認することに関心があります。 =)特に、time_1とtime_2にGistインデックスがある場合。
次に、ラテラル結合を使用した1つの試みを示します。
select time_1, time_2
from tbl1
cross join lateral (
select time_2
from tbl2
order by case when time_1 > time_2 then age(time_1,time_2)
else age(time_2,time_1)
end
fetch first 1 rows only
) as t;
別の可能性は、サブクエリを使用することです:
select time_1, (
select time_2
from tbl2
order by case when time_1 > time_2 then age(time_1,time_2)
else age(time_2,time_1)
end
fetch first 1 rows only
)
from tbl1;
タイムスタンプの差の絶対値を決定するより洗練された方法がおそらくあります。注目に値するのは、テーブルの順序を変更すると結果が異なることです。
select dt1.time_1,
dt1.time_2
from
(select row_number() over(partition by time_1 order by abs(extract('Epoch' from time_1) - extract('Epoch' from time_2)) asc) as rn,
time_1,
time_2
from tbl1
cross
join tbl2
) dt1
where dt1.rn = 1
order by dt1.time_1
dt1
...cross join
(別名デカルト積)を実行します...Epoch
回の差の絶対値を使用して、同じtime_1
値を持つ行のグループの行番号付けを並べ替えます。その後...dt1.rn = 1
値の最初の行(time_1
)に出力を制限します結果:
time_1 | time_2
------------------- | -------------------
2017-09-06 15:26:02 | 2017-09-06 15:23:59
2017-09-06 15:26:03 | 2017-09-06 15:23:59
2017-09-06 15:28:01 | 2017-09-06 15:29:01
2017-09-06 15:40:00 | 2017-09-06 15:40:00
注:最後のtime_1 = 2017-09-06 15:40:00
については、質問で提案されたものとは異なるtime_2
の一致が得られます。
-- suggested in the question:
time_1 time_2
--------------------- --------------------
2017-09-06 15:40:00 2017-09-06 15:45:58
これが dbfiddle です