You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL:按规则为GPS点分配过夜到访场合编号

PostgreSQL GPS点到访场合编号分配优化请求

需求说明

需要为每个person_id(人员ID)的所有trip_id中,满足overnight = 'Yes'的每个point_id(GPS点ID)分配对应的occasion(到访场合编号),规则如下:

  • 同一trip_id内,若同一place_id(overnight='Yes')的两个point_id之间存在至少一个属于其他place_id(overnight='Yes')的点,则这两个点需视为不同场合,即重访算作不同场合。
  • 不同trip_id内,同一place_id(overnight='Yes')的point_id需视为不同场合。

表结构与示例数据

CREATE TABLE my_table (
    point_id INT,
    trip_id INT,
    person_id INT,
    place_id INT,
    overnight VARCHAR,
    occasion INT
);

INSERT INTO my_table (point_id, trip_id, person_id, place_id, overnight, occasion) VALUES
(1, 5, 1, 9, 'Yes', 1),
(2, 5, 1, 10, 'Yes', 1),
(3, 5, 1, 10, 'Yes', 1),
(4, 5, 1, 9, NULL, NULL),
(5, 5, 1, 9, 'Yes', 2),
(6, 5, 1, 10, 'Yes', 2),
(7, 5, 1, 9, 'Yes', 3),
(8, 5, 1, 10, 'Yes', 3),
(9, 5, 1, 10, 'No', NULL),
(10, 5, 1, 10, 'No', NULL),
(11, 5, 1, 10, 'Yes', 3),
(12, 95, 2, NULL, NULL, NULL),
(13, 95, 2, 9, 'No', NULL),
(14, 96, 2, 9, 'Yes', 1),
(15, 96, 2, NULL, NULL, NULL),
(16, 96, 2, 9, 'Yes', 1),
(17, 97, 2, NULL, NULL, NULL),
(18, 97, 2, NULL, NULL, NULL),
(19, 97, 2, 9, 'Yes', 2),
(20, 98, 2, 9, 'Yes', 3),
(21, 98, 2, 9, 'No', NULL),
(22, 99, 2, 10, 'No', NULL),
(23, 99, 2, 9, 'Yes', 4),
(24, 99, 2, 10, 'No', NULL),
(25, 99, 2, 10, 'Yes', 1);

当前查询语句

当前查询输出的final_visit_rank字段与预期的occasion一致,但不确定该方案在数十万行数据集下的效率与优雅性,寻求优化建议:

with t_revisit as (
select  *, 
        case when place_id is not distinct from lag(place_id) over (
            partition by person_id order by point_id rows between unbounded preceding and current row) and 
                trip_id is not distinct from lag(trip_id) over (
                    partition by person_id order by point_id rows between unbounded preceding and current row)
                        then 1
             else 0
        end as revisit
from my_table
where overnight = 'Yes'
), 

t_visit_rank as (
select  *,
        row_number() over (
            partition by person_id, place_id order by trip_id, point_id 
                rows between unbounded preceding and current row) as visit_rank
from t_revisit
where revisit = 0)

select  t.*, visit_rank, 
        case when t.revisit = 1 
                then lag(visit_rank) over (
                    partition by t.person_id, t.place_id, t.overnight order by t.point_id 
                        rows between unbounded preceding and current row)
            else visit_rank
        end as final_visit_rank
from (select my_table.*, revisit
      from my_table
      left join t_revisit
      on my_table.point_id = t_revisit.point_id) t
left join t_visit_rank
on t.point_id = t_visit_rank.point_id
order by person_id, point_id; 

内容的提问来源于stack exchange,提问作者Beau

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 01:55:28