del*_*kov 6 postgresql join time
我有 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' );
Run Code Online (Sandbox Code Playgroud)
我想加入表格,因此对于 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
Run Code Online (Sandbox Code Playgroud)
我知道如何找到最近时间的单个值:
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;
Run Code Online (Sandbox Code Playgroud)
btree_gist
和<->
您真的希望<->
通过内部tstz_dist
. 这是有效的,因为您并不真正关心间隔。首先你需要添加扩展名,
CREATE EXTENSION btree_gist;
Run Code Online (Sandbox Code Playgroud)
然后
SELECT DISTINCT ON (time_1) time_1, time_2
FROM tbl1
CROSS JOIN tbl2
ORDER BY time_1, time_1 <-> time_2;
Run Code Online (Sandbox Code Playgroud)
如果要进行交叉连接的行太多,则横向解决方案可能会更好。
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;
Run Code Online (Sandbox Code Playgroud)
有兴趣看到有关基准的报告。=) 特别是如果您在 time_1 和 time_2 上有 GIST 索引。
这是使用横向连接的一种尝试:
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;
Run Code Online (Sandbox Code Playgroud)
另一种可能性是使用子查询:
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;
Run Code Online (Sandbox Code Playgroud)
可能有一种更优雅的方法来确定时间戳差的绝对值。值得注意的是,如果改变表的顺序,结果将会不同。
归档时间: |
|
查看次数: |
5357 次 |
最近记录: |