Huy Do
Huy Do

Reputation: 470

How to find near stores from store location (latitude, longitude) from store table?

I have a Postgresql table named stores which contains a store's location (lat, long), and I can find near stores from a store using query. However, I can't find a query to create a 'ready'-generated table which create list of near stores for every store. This is the query I used to get list of near stores:

select mds.id, mds.store_name
    from public.store mds,
    (select latitude, longitude from public.store where id = '3f6077c0-c56b-4570-883f-4c16dc19855e') as st,
    sqrt(111.12 * (mds.latitude - st.latitude) * 111.12 * (mds.latitude - st.latitude) + (111.12 * (mds.longitude - st.longitude) * cos(st.latitude / 92.215)) * (111.12 * (mds.longitude - st.longitude) * cos(st.latitude / 92.215))) as distance
where distance <= 20
order by distance
limit 100

I can't replace the '3f6077c0-c56b-4570-883f-4c16dc19855e' by public.store.id. The table columns of store table is:

| id  | store_name  | latitude   |  longitude  |

Please help me with this request. Thank you very much.

Upvotes: 1

Views: 499

Answers (1)

Jim Jones
Jim Jones

Reputation: 19653

Spatial queries are better handled using the extension PostGIS. It has loads of really handy functions that make spatial queries very easy to write and to maintain. My suggestion:

Install Postgis (see this other answer)

Add a geometry column to your table, e.g.

SELECT AddGeometryColumn ('public','store','geom',4326,'POINT',2);

Create point geometries based on your latitude and longitude values:

UPDATE store SET geom = ST_MakePoint(longitude,latitude);

Index it (to make queries faster)

CREATE INDEX idx_store_geom ON store USING gist (geom);

After that, this is how a query to list the nearest neighbours of a given point would look like:

SELECT * FROM store
ORDER BY geom <-> ST_SetSRID(ST_MakePoint(92.215,111.12),4326)

Or if you want the nearest store to each store ..

SELECT * FROM store mds,
LATERAL (SELECT store_name,ST_Distance(geom,mds.geom) FROM store
         WHERE id <> mds.id
         ORDER BY geom <-> mds.geom
         LIMIT 1) c (closest_store,distance);
  • The operator <-> stands for distance, so using it in the ORDER BY clause with LIMIT 1 selects only the record that is closest to a reference geometry.
  • 4326 stands for the spatial reference system WGS84. It might vary depending on your coordinates.

Demo: db<>fiddle

Upvotes: 4

Related Questions