我有下面的函数get_untracked_moves
。我的目标是,对于两个日期范围之间的所有数据,找到比p_separation_distance
更远的连续事件。
例如:
如果事件1和事件2相隔40米,当p_separation_distance为100米时,将返回一条记录,其中事件1的关联cont_name为source_name
,事件2的cont_name为{ {1}}。
target_name
该函数可以很好地创建,但是当我用它来运行它时:
CREATE FUNCTION get_untracked_moves(IN p_since_date TIMESTAMP WITHOUT TIME ZONE, IN p_before_date TIMESTAMP WITHOUT TIME ZONE, IN p_separation_distance INTEGER)
RETURNS TABLE ( id INTEGER,
asset_name CHARACTER VARYING,
source_name CHARACTER VARYING,
target_name CHARACTER VARYING,
source_time TIMESTAMP WITHOUT TIME ZONE,
target_time TIMESTAMP WITHOUT TIME ZONE,
source_lat DOUBLE PRECISION,
source_lon DOUBLE PRECISION,
target_lat DOUBLE PRECISION,
target_lon DOUBLE PRECISION ) AS $$
DECLARE
d_previous_location GEOMETRY;
d_previous_name CHARACTER VARYING;
d_previous_time TIMESTAMP WITHOUT TIME ZONE;
d_cur record;
BEGIN
-- Begin @ 0,0
d_previous_location := st_setsrid(st_makepoint(0,0), 4326);
d_previous_name := '';
d_previous_time := NULL;
FOR d_cur
IN
SELECT
rank() OVER (PARTITION BY events.asset_id ORDER BY events.event_time) AS idx,
tags.id asset_id,
tags.name asset_name,
d_previous_name,
conts.name cont_name,
events.position,
events.event_time evt_time
FROM
events
JOIN
assets tags ON tags.id = events.asset_id
JOIN
assets conts ON conts.id = events.container_asset_id
WHERE
events.event_time >= p_since_date
AND
events.event_time <= p_before_date
LOOP
IF (d_previous_time = NULL) THEN
d_previous_time := events.event_time;
END IF;
IF (st_distancesphere(events.position, d_previous_location)>=p_separation_distance) THEN
RETURN NEXT;
END IF;
d_previous_location := events.position;
d_previous_name := conts.name;
d_previous_time := events.event_time;
END LOOP;
END;
$$
LANGUAGE plpgsql VOLATILE;
我明白了:
select * from get_untracked_moves('2015-11-1', '2015-12-1', 10000);
我在这里缺少什么?我认为在我的ERROR: missing FROM-clause entry for table "events"
LINE 1: SELECT (st_distancesphere(events.position, d_previous_locati...
^
QUERY: SELECT (st_distancesphere(events.position, d_previous_location)>=p_separation_distance)
CONTEXT: PL/pgSQL function "get_untracked_moves" line 41 at IF
********** Error **********
ERROR: missing FROM-clause entry for table "events"
SQL state: 42P01
Context: PL/pgSQL function "get_untracked_moves" line 41 at IF
声明中包含FROM events
就足够了。
答案 0 :(得分:2)
循环的每次传递都被赋予包含选择结果集的相应行的记录的值。因此events
在循环内部不可见。而是使用d_cur.position
来引用该列。
lag
窗口函数并摆脱凌乱的循环。
建议检查此查询:
select idx, asset_id, asset_name, previous_name, cont_name, position, evt_time
from (
select
rank() over (partition by e.asset_id order by e.event_time) as idx,
st_distancesphere(
e.position,
lag(e.position, 1, e.position) over (order by e.event_time)
) >= p_separation_distance as b,
t.id as asset_id,
t.name as asset_name,
lag(c.name, 1) as previous_name,
c.name as cont_name,
e.position,
e.event_time as evt_time
from
events e
inner join
assets tags on t.id = e.asset_id
inner join
assets c on c.id = e.container_asset_id
where
e.event_time >= p_since_date
and
e.event_time <= p_before_date
) s
where b