PostgreSQL选择与给定间隔匹配的最接近的时间点

时间:2019-07-01 12:13:01

标签: postgresql unique minimum groupwise

我希望弄清楚我是否可以解决SQL中的以下问题,还是最好从脚本语言中选择值,然后从那里进行批量更新。

有一些时间点,并且有一些时间间隔,该时间间隔由时间间隔的中心和距该中心的最大持续时间定义,因此所有时间间隔均为10分钟。中心可以彼此处于任何持续时间,点可以彼此处于任何持续时间。希望选择所有时间间隔以及一个或零个点,以便不分配每个点或仅分配一个间隔。如果一个点匹配一个以上的间隔,反之亦然,则应选择这些点,以使两个点和间隔中心之间的总持续时间最小化。

样本数据

interval
id centertime
1 2001-01-01 12.00     # starts at 11.50 ends at 12.10
2 2001-01-01 12.15     # starts at 12.05 ends at 12.25
3 2001-01-01 12.20     # starts at 12.10 ends at 12.30

point
id time
21 2001-01-01 12.00     
22 2001-01-01 12.11
23 2001-01-01 12.17
24 2001-01-01 12.19

所需结果:

interval_id point_id
1 21
2 23
3 24

说明

点21与间隔1的中心完全匹配,因此没有分配其他任何东西。

点23比3更接近区间2,但是 点24甚至更接近3,因此将间隔3分配给点24。

点22是最接近间隔2的剩余点,因此已被分配。

点21在间隔2内,但点22可用且更近,因此21未分配给间隔,因此不会出现在结果中。

点23甚至更接近3,所以22是 最接近的剩余一个

1 个答案:

答案 0 :(得分:0)

好吧,我明白了。

它使用横向联接来计算从每个中心时间到每个点的持续时间,并将其包装在附加的SELECT中,以使用有序窗口函数仅获得最接近的匹配项。

SELECT * FROM (
    SELECT
        i.id as interval_id,
        p.id as point_id,
        p.duration,
        ROW_NUMBER() OVER (PARTITION BY i.id ORDER BY duration) AS rownumber
    FROM "interval" i
    LEFT JOIN LATERAL (
        SELECT
            p1.id,
            p1."time",
            ABS(EXTRACT(EPOCH FROM i.centertime - p1."time")) as duration
        FROM "point" p1
        WHERE p1."time"
            BETWEEN i.centertime - interval '10 minute'
            AND i.centertime + interval '10 minute'
     ) p on true)
     AS q
WHERE rownumber=1;