如何仅聚合 sql 中的邻居记录?
How to aggregate only neighbour records in sql?
让我们假设我有一个名为位置的 table,它包含源位置的记录以及记录该位置的时间。
id
source_id
ts
position
1
3134
2021-02-21 20:48:08.488359
...
2
3134
2021-02-21 20:48:09.123422
...
...
...
...
...
ts是timestamp的缩写,position是postgis格式的,不过这道题并不重要
我还有另一个 table 区域:
id
area
1
...
2
...
...
...
该区域是 postgis 格式的多边形。
例如我可以测试一个点是否在一个区域内
SELECT locations.source_id, zones.id, locations.ts
from locations inner join
zones
on ST_Contains(zones.area, locations.position);
会告诉我哪个源在哪个区域。
我想要的是产生以下输出的查询:
locations.source_id
zones.id
in_zone_time
3134
1
1 mins
3134
2
4 mins
3134
1
2 mins
...
...
...
所以它会告诉我源 3134 在 1 区停留了 1 分钟,然后在 2 区停留了 4 分钟,然后又在 1 区停留了 2 分钟。
这种方式如何实现聚合?
您可以添加一个标志,然后将其视为间隙和孤岛问题。不清楚time
是怎么算出来的,但是思路是:
select source_id, id, min(ts), max(ts), max(ts) - min(ts) as diff
from (select l.source_id, z.id, l.ts,
row_number() over (partition by l.source_id order by l.ts) as seqnumm
row_number() over (partition by l.source_id, z.id order by l.ts) as seqnum_2
from locations l inner join
zones
on ST_Contains(z.area, l.position)
) lz
group by (seqnum - seqnum_2);
这里做了一些假设:
- 所有点都在一个区域内。或者至少,你只关心一个区域内的点数。
- 点数一次只在一个区域。
- 在一个区域中花费的时间是最早和最后一次进入该区域的记录之间的差值。
这些对你的问题的解释都比较合理,但是可以放宽。如果您的要求不同,我建议您提出 new 问题,明确说明问题的细节。示例数据和相应的预期结果非常有帮助。
让我们假设我有一个名为位置的 table,它包含源位置的记录以及记录该位置的时间。
id | source_id | ts | position |
---|---|---|---|
1 | 3134 | 2021-02-21 20:48:08.488359 | ... |
2 | 3134 | 2021-02-21 20:48:09.123422 | ... |
... | ... | ... | ... |
ts是timestamp的缩写,position是postgis格式的,不过这道题并不重要
我还有另一个 table 区域:
id | area |
---|---|
1 | ... |
2 | ... |
... | ... |
该区域是 postgis 格式的多边形。
例如我可以测试一个点是否在一个区域内
SELECT locations.source_id, zones.id, locations.ts
from locations inner join
zones
on ST_Contains(zones.area, locations.position);
会告诉我哪个源在哪个区域。
我想要的是产生以下输出的查询:
locations.source_id | zones.id | in_zone_time |
---|---|---|
3134 | 1 | 1 mins |
3134 | 2 | 4 mins |
3134 | 1 | 2 mins |
... | ... | ... |
所以它会告诉我源 3134 在 1 区停留了 1 分钟,然后在 2 区停留了 4 分钟,然后又在 1 区停留了 2 分钟。
这种方式如何实现聚合?
您可以添加一个标志,然后将其视为间隙和孤岛问题。不清楚time
是怎么算出来的,但是思路是:
select source_id, id, min(ts), max(ts), max(ts) - min(ts) as diff
from (select l.source_id, z.id, l.ts,
row_number() over (partition by l.source_id order by l.ts) as seqnumm
row_number() over (partition by l.source_id, z.id order by l.ts) as seqnum_2
from locations l inner join
zones
on ST_Contains(z.area, l.position)
) lz
group by (seqnum - seqnum_2);
这里做了一些假设:
- 所有点都在一个区域内。或者至少,你只关心一个区域内的点数。
- 点数一次只在一个区域。
- 在一个区域中花费的时间是最早和最后一次进入该区域的记录之间的差值。
这些对你的问题的解释都比较合理,但是可以放宽。如果您的要求不同,我建议您提出 new 问题,明确说明问题的细节。示例数据和相应的预期结果非常有帮助。