【问题标题】:PostgreSQL select closest points in time that match given intervalsPostgreSQL 选择与给定时间间隔匹配的最近时间点
【发布时间】:2019-11-12 02:23:52
【问题描述】:

我正在寻找是否可以在 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 是 最接近的剩余一个

【问题讨论】:

  • 样本数据、期望的结果、清晰的解释(时间戳、时间段、重叠......这很令人困惑)和适当的数据库标签都会有所帮助。
  • @GordonLinoff 根据您的宝贵反馈进行了编辑。问题并非微不足道,但我希望现在已经明确定义。
  • 如果不是因为“应采取点以尽量减少总持续时间”,您可以使用如下内容:rextester.com/XXACM88895
  • @a_horse_with_no_name 非常酷,我对横向连接一无所知。我修改了您很酷的查询,因此如果删除了所有包含重复间隔 ID 的行,它将执行我想要的操作。更新/冲突可能有效,但可以在选择中完成吗? rextester.com/LVEL85019
  • @a_horse_with_no_name 得到了一个将横向连接与窗口函数相结合的解决方案,以消除不需要的匹配。谢谢!!!

标签: postgresql unique minimum groupwise


【解决方案1】:

好的,我知道了。

它使用横向连接来计算从每个中心时间到每个点的持续时间,并将其包装在一个额外的 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;

【讨论】:

  • 毕竟没有得到它——我最终找到了一个将这种方法与递归 CTE 相结合的解决方案,以免重复分配。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-07
  • 2015-09-03
  • 2012-02-03
  • 1970-01-01
  • 2017-01-30
  • 2020-03-08
相关资源
最近更新 更多