我希望弄清楚我是否可以解决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是 最接近的剩余一个
答案 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;