0

2 つの異なるテーブルでジオコード リバース クエリを解決する方法を見つけようとしています。1 つは道路の住所/緯度経度テーブルで、もう 1 つは gps トラッカーの緯度経度テーブルです。

ジオコードの逆を取得するための私のクエリ

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 に答える