0

我试图找到一种方法来解决两个不同表上的地理编码反向查询,其中一个是街道地址/纬度 lng 表,另一个是来自 gps 跟踪器的纬度 lng 表。

我的查询获取反向地理编码

SELECT street_name, distance(ST_SetSRID(geom, 4326), geomfromtext('POINT(-71.536252 -16.398624)', 4326)) AS dist 
FROM vias_polyline ORDER BY dist ASC, gid DESC LIMIT 1;

我对获取最后一个 gps 位置的查询

CREATE OR REPLACE FUNCTION gps_get_live_location (
    _imeis varchar(8)
)
RETURNS TABLE (
    imei varchar,
    date_time_process timestamp with time zone, 
    latitude double precision, 
    longitude double precision
) AS $func$
DECLARE 
    arr varchar[];
BEGIN
    arr := regexp_split_to_array(_imeis, E'\\s+');
    FOR i IN 1..array_length(arr, 1) LOOP
        RETURN QUERY SELECT 
        imei,
        date_time_process,
        latitude,
        longitude
        FROM gpstracking_device_tracks
        WHERE imei = arr[i]::VARCHAR
        AND date_time_process >= date_trunc('hour', now()) 
        AND date_time_process <= NOW()
        ORDER BY date_time_process DESC
        LIMIT 1;
    END LOOP;
    RETURN;
END;
$func$ 
LANGUAGE plpgsql VOLATILE SECURITY DEFINER;

我需要的是一种方法来做一个简单的查询来获取最后位置查询的地理编码反向

我希望有可能,我的第一个解决方案是

CREATE OR REPLACE FUNCTION gps_get_live_location (
    _imeis varchar(8)
)
RETURNS TABLE (
    imei varchar,
    device_id integer,
    date_time_process timestamp with time zone, 
    latitude double precision, 
    longitude double precision, 
    course smallint, 
    speed smallint, 
    mileage integer,
    gps_signal smallint,
    gsm_signal smallint,
    alarm_status boolean,
    gsm_status boolean,
    vehicle_status boolean,
    alarm_over_speed boolean,
    other text
) AS $func$
DECLARE 
    arr varchar[];
BEGIN
    arr := regexp_split_to_array(_imeis, E'\\s+');
    FOR i IN 1..array_length(arr, 1) LOOP
        RETURN QUERY 
        SELECT gpstracking_device_tracks.*,
        vias_polyline.urbanizaci, 
        vias_polyline.nombre_via, 
        distance(ST_SetSRID(vias_polyline.geom, 4326), ST_SetSRID(gpstracking_device_tracks.point, 4326)) AS dist
        FROM 
        (SELECT 
        gpstracking_device_tracks.imei,
        gpstracking_device_tracks.device_id, 
        gpstracking_device_tracks.date_time_process,
        gpstracking_device_tracks.latitude,
        gpstracking_device_tracks.longitude,
        gpstracking_device_tracks.course,
        gpstracking_device_tracks.speed,
        gpstracking_device_tracks.mileage,
        gpstracking_device_tracks.gps_signal,
        gpstracking_device_tracks.gsm_signal,
        gpstracking_device_tracks.alarm_status,
        gpstracking_device_tracks.gps_status,
        gpstracking_device_tracks.vehicle_status,
        gpstracking_device_tracks.alarm_over_speed,
        gpstracking_device_tracks.other,
        gpstracking_device_tracks.point
        FROM gpstracking_device_tracks
        WHERE gpstracking_device_tracks.imei = arr[i]::VARCHAR
        AND gpstracking_device_tracks.date_time_process >= date_trunc('hour', now()) 
        AND gpstracking_device_tracks.date_time_process <= NOW()
        ORDER BY gpstracking_device_tracks.date_time_process DESC
        LIMIT 1) AS gpstracking_device_tracks, vias_polyline 
        ORDER BY dist ASC, gid DESC 
        LIMIT 1;
    END LOOP;
    RETURN;
END;
$func$ 
LANGUAGE plpgsql VOLATILE SECURITY DEFINER;

但是我不完全确定这是一个好的答案

4

1 回答 1

0

Your way is reasonable. I would recommend changing your implicit cross join to an explicit one. This improves readability and clarity. However, as it is, there isn't much you can do to get around this. Other things you could try would be:

  1. Moving your inline view into a CTE (this has optimization implications so be aware it could be a win or a loss, but I don't think it matters here)
  2. Moving your inline view into a formal one (this has the danger however of forgetting what is going on in your view when you re-use it somewhere else and thus causing needless performance issues).
于 2013-11-14T06:36:13.203 回答